summaryrefslogtreecommitdiff
path: root/lib/ansible/module_utils/network/ios
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ansible/module_utils/network/ios')
-rw-r--r--lib/ansible/module_utils/network/ios/argspec/acl_interfaces/acl_interfaces.py66
-rw-r--r--lib/ansible/module_utils/network/ios/argspec/acls/acls.py593
-rw-r--r--lib/ansible/module_utils/network/ios/argspec/facts/facts.py24
-rw-r--r--lib/ansible/module_utils/network/ios/argspec/interfaces/interfaces.py47
-rw-r--r--lib/ansible/module_utils/network/ios/argspec/l2_interfaces/l2_interfaces.py57
-rw-r--r--lib/ansible/module_utils/network/ios/argspec/l3_interfaces/l3_interfaces.py53
-rw-r--r--lib/ansible/module_utils/network/ios/argspec/lacp/lacp.py47
-rw-r--r--lib/ansible/module_utils/network/ios/argspec/lacp_interfaces/lacp_interfaces.py48
-rw-r--r--lib/ansible/module_utils/network/ios/argspec/lag_interfaces/lag_interfaces.py52
-rw-r--r--lib/ansible/module_utils/network/ios/argspec/lldp_global/lldp_global.py58
-rw-r--r--lib/ansible/module_utils/network/ios/argspec/lldp_interfaces/lldp_interfaces.py52
-rw-r--r--lib/ansible/module_utils/network/ios/argspec/static_routes/static_routes.py85
-rw-r--r--lib/ansible/module_utils/network/ios/argspec/vlans/vlans.py50
-rw-r--r--lib/ansible/module_utils/network/ios/config/acl_interfaces/acl_interfaces.py405
-rw-r--r--lib/ansible/module_utils/network/ios/config/acls/acls.py717
-rw-r--r--lib/ansible/module_utils/network/ios/config/interfaces/interfaces.py295
-rw-r--r--lib/ansible/module_utils/network/ios/config/l2_interfaces/l2_interfaces.py336
-rw-r--r--lib/ansible/module_utils/network/ios/config/l3_interfaces/l3_interfaces.py328
-rw-r--r--lib/ansible/module_utils/network/ios/config/lacp/lacp.py189
-rw-r--r--lib/ansible/module_utils/network/ios/config/lacp_interfaces/lacp_interfaces.py260
-rw-r--r--lib/ansible/module_utils/network/ios/config/lag_interfaces/lag_interfaces.py296
-rw-r--r--lib/ansible/module_utils/network/ios/config/lldp_global/lldp_global.py238
-rw-r--r--lib/ansible/module_utils/network/ios/config/lldp_interfaces/lldp_interfaces.py270
-rw-r--r--lib/ansible/module_utils/network/ios/config/static_routes/static_routes.py532
-rw-r--r--lib/ansible/module_utils/network/ios/config/vlans/vlans.py292
-rw-r--r--lib/ansible/module_utils/network/ios/facts/acl_interfaces/acl_interfaces.py122
-rw-r--r--lib/ansible/module_utils/network/ios/facts/acls/acls.py498
-rw-r--r--lib/ansible/module_utils/network/ios/facts/facts.py79
-rw-r--r--lib/ansible/module_utils/network/ios/facts/interfaces/interfaces.py97
-rw-r--r--lib/ansible/module_utils/network/ios/facts/l2_interfaces/l2_interfaces.py114
-rw-r--r--lib/ansible/module_utils/network/ios/facts/l3_interfaces/l3_interfaces.py124
-rw-r--r--lib/ansible/module_utils/network/ios/facts/lacp/lacp.py83
-rw-r--r--lib/ansible/module_utils/network/ios/facts/lacp_interfaces/lacp_interfaces.py102
-rw-r--r--lib/ansible/module_utils/network/ios/facts/lag_interfaces/lag_interfaces.py118
-rw-r--r--lib/ansible/module_utils/network/ios/facts/legacy/base.py380
-rw-r--r--lib/ansible/module_utils/network/ios/facts/lldp_global/lldp_global.py90
-rw-r--r--lib/ansible/module_utils/network/ios/facts/lldp_interfaces/lldp_interfaces.py108
-rw-r--r--lib/ansible/module_utils/network/ios/facts/static_routes/static_routes.py225
-rw-r--r--lib/ansible/module_utils/network/ios/facts/vlans/vlans.py144
-rw-r--r--lib/ansible/module_utils/network/ios/ios.py183
-rw-r--r--lib/ansible/module_utils/network/ios/providers/cli/config/base.py77
-rw-r--r--lib/ansible/module_utils/network/ios/providers/cli/config/bgp/address_family.py140
-rw-r--r--lib/ansible/module_utils/network/ios/providers/cli/config/bgp/neighbors.py196
-rw-r--r--lib/ansible/module_utils/network/ios/providers/cli/config/bgp/process.py140
-rw-r--r--lib/ansible/module_utils/network/ios/providers/module.py62
-rw-r--r--lib/ansible/module_utils/network/ios/providers/providers.py120
-rw-r--r--lib/ansible/module_utils/network/ios/utils/utils.py328
47 files changed, 0 insertions, 8920 deletions
diff --git a/lib/ansible/module_utils/network/ios/argspec/acl_interfaces/acl_interfaces.py b/lib/ansible/module_utils/network/ios/argspec/acl_interfaces/acl_interfaces.py
deleted file mode 100644
index 608cf6e728..0000000000
--- a/lib/ansible/module_utils/network/ios/argspec/acl_interfaces/acl_interfaces.py
+++ /dev/null
@@ -1,66 +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 ios_acl_interfaces module
-"""
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-class Acl_InterfacesArgs(object):
- """The arg spec for the ios_acl_interfaces module
- """
-
- argument_spec = {
- 'config': {
- 'elements': 'dict',
- 'options': {
- 'name': {'required': True, 'type': 'str'},
- 'access_groups': {
- 'type': 'list',
- 'elements': 'dict',
- 'options': {
- 'afi': {'required': True, 'choices': ['ipv4', 'ipv6'], 'type': 'str'},
- 'acls': {
- 'type': 'list',
- 'elements': 'dict',
- 'options': {
- 'name': {'required': True, 'type': 'str'},
- 'direction': {'required': True, 'choices': ['in', 'out'], 'type': 'str'}
- }
- }
- }
- }
- },
- 'type': 'list'
- },
- 'running_config': {'type': 'str'},
- 'state': {
- 'choices': ['merged', 'replaced', 'overridden', 'deleted', 'gathered', 'rendered', 'parsed'],
- 'default': 'merged',
- 'type': 'str'
- }
- }
diff --git a/lib/ansible/module_utils/network/ios/argspec/acls/acls.py b/lib/ansible/module_utils/network/ios/argspec/acls/acls.py
deleted file mode 100644
index ca8982e557..0000000000
--- a/lib/ansible/module_utils/network/ios/argspec/acls/acls.py
+++ /dev/null
@@ -1,593 +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 ios_acls module
-"""
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-class AclsArgs(object):
- """The arg spec for the ios_acls module
- """
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- 'config': {
- 'elements': 'dict',
- 'options': {
- 'afi': {
- 'required': True,
- 'choices': ['ipv4', 'ipv6'],
- 'type': 'str'
- },
- 'acls': {
- 'elements': 'dict',
- 'type': 'list',
- 'options': {
- 'name': {
- 'required': True,
- 'type': 'str'
- },
- 'acl_type': {
- 'choices': ['extended', 'standard'],
- 'type': 'str'
- },
- 'aces': {
- 'elements': 'dict',
- 'type': 'list',
- 'options': {
- 'grant': {
- 'choices': ['permit', 'deny'],
- 'type': 'str'
- },
- 'sequence': {
- 'type': 'int'
- },
- 'source': {
- 'type':
- 'dict',
- 'mutually_exclusive':
- [['address', 'any', 'host'],
- ['wildcard_bits', 'any', 'host']],
- 'options': {
- 'address': {
- 'type': 'str'
- },
- 'wildcard_bits': {
- 'type': 'str'
- },
- 'any': {
- 'type': 'bool'
- },
- 'host': {
- 'type': 'str'
- },
- 'port_protocol': {
- 'type': 'dict',
- 'options': {
- 'eq': {
- 'type': 'str'
- },
- 'gt': {
- 'type': 'str'
- },
- 'lt': {
- 'type': 'str'
- },
- 'neq': {
- 'type': 'str'
- },
- 'range': {
- 'type': 'dict',
- 'options': {
- 'start': {
- 'type': 'int'
- },
- 'end': {
- 'type': 'int'
- }
- }
- }
- }
- }
- },
- },
- 'destination': {
- 'type':
- 'dict',
- 'mutually_exclusive':
- [['address', 'any', 'host'],
- ['wildcard_bits', 'any', 'host']],
- 'options': {
- 'address': {
- 'type': 'str'
- },
- 'wildcard_bits': {
- 'type': 'str'
- },
- 'any': {
- 'type': 'bool'
- },
- 'host': {
- 'type': 'str'
- },
- 'port_protocol': {
- 'type': 'dict',
- 'options': {
- 'eq': {
- 'type': 'str'
- },
- 'gt': {
- 'type': 'str'
- },
- 'lt': {
- 'type': 'str'
- },
- 'neq': {
- 'type': 'str'
- },
- 'range': {
- 'type': 'dict',
- 'options': {
- 'start': {
- 'type': 'int'
- },
- 'end': {
- 'type': 'int'
- }
- }
- }
- }
- }
- }
- },
- 'protocol': {
- 'type': 'str'
- },
- 'protocol_options': {
- 'type': 'dict',
- 'options': {
- 'protocol_number': {
- 'type': 'int'
- },
- 'ahp': {
- 'type': 'bool'
- },
- 'eigrp': {
- 'type': 'bool'
- },
- 'esp': {
- 'type': 'bool'
- },
- 'gre': {
- 'type': 'bool'
- },
- 'hbh': {
- 'type': 'bool'
- },
- 'icmp': {
- 'type': 'dict',
- 'options': {
- 'administratively_prohibited':
- {
- 'type': 'bool'
- },
- 'alternate_address': {
- 'type': 'bool'
- },
- 'conversion_error': {
- 'type': 'bool'
- },
- 'dod_host_prohibited': {
- 'type': 'bool'
- },
- 'dod_net_prohibited': {
- 'type': 'bool'
- },
- 'echo': {
- 'type': 'bool'
- },
- 'echo_reply': {
- 'type': 'bool'
- },
- 'general_parameter_problem': {
- 'type': 'bool'
- },
- 'host_isolated': {
- 'type': 'bool'
- },
- 'host_precedence_unreachable':
- {
- 'type': 'bool'
- },
- 'host_redirect': {
- 'type': 'bool'
- },
- 'host_tos_redirect': {
- 'type': 'bool'
- },
- 'host_tos_unreachable': {
- 'type': 'bool'
- },
- 'host_unknown': {
- 'type': 'bool'
- },
- 'host_unreachable': {
- 'type': 'bool'
- },
- 'information_reply': {
- 'type': 'bool'
- },
- 'information_request': {
- 'type': 'bool'
- },
- 'mask_reply': {
- 'type': 'bool'
- },
- 'mask_request': {
- 'type': 'bool'
- },
- 'mobile_redirect': {
- 'type': 'bool'
- },
- 'net_redirect': {
- 'type': 'bool'
- },
- 'net_tos_redirect': {
- 'type': 'bool'
- },
- 'net_tos_unreachable': {
- 'type': 'bool'
- },
- 'net_unreachable': {
- 'type': 'bool'
- },
- 'network_unknown': {
- 'type': 'bool'
- },
- 'no_room_for_option': {
- 'type': 'bool'
- },
- 'option_missing': {
- 'type': 'bool'
- },
- 'packet_too_big': {
- 'type': 'bool'
- },
- 'parameter_problem': {
- 'type': 'bool'
- },
- 'port_unreachable': {
- 'type': 'bool'
- },
- 'precedence_unreachable': {
- 'type': 'bool'
- },
- 'protocol_unreachable': {
- 'type': 'bool'
- },
- 'reassembly_timeout': {
- 'type': 'bool'
- },
- 'redirect': {
- 'type': 'bool'
- },
- 'router_advertisement': {
- 'type': 'bool'
- },
- 'router_solicitation': {
- 'type': 'bool'
- },
- 'source_quench': {
- 'type': 'bool'
- },
- 'source_route_failed': {
- 'type': 'bool'
- },
- 'time_exceeded': {
- 'type': 'bool'
- },
- 'timestamp_reply': {
- 'type': 'bool'
- },
- 'timestamp_request': {
- 'type': 'bool'
- },
- 'traceroute': {
- 'type': 'bool'
- },
- 'ttl_exceeded': {
- 'type': 'bool'
- },
- 'unreachable': {
- 'type': 'bool'
- },
- }
- },
- 'igmp': {
- 'type': 'dict',
- 'options': {
- 'dvmrp': {
- 'type': 'bool'
- },
- 'host_query': {
- 'type': 'bool'
- },
- 'mtrace_resp': {
- 'type': 'bool'
- },
- 'mtrace_route': {
- 'type': 'bool'
- },
- 'pim': {
- 'type': 'bool'
- },
- 'trace': {
- 'type': 'bool'
- },
- 'v1host_report': {
- 'type': 'bool'
- },
- 'v2host_report': {
- 'type': 'bool'
- },
- 'v2leave_group': {
- 'type': 'bool'
- },
- 'v3host_report': {
- 'type': 'bool'
- }
- }
- },
- 'ip': {
- 'type': 'bool'
- },
- 'ipv6': {
- 'type': 'bool'
- },
- 'ipinip': {
- 'type': 'bool'
- },
- 'nos': {
- 'type': 'bool'
- },
- 'ospf': {
- 'type': 'bool'
- },
- 'pcp': {
- 'type': 'bool'
- },
- 'pim': {
- 'type': 'bool'
- },
- 'sctp': {
- 'type': 'bool'
- },
- 'tcp': {
- 'options': {
- 'ack': {
- 'type': 'bool'
- },
- 'established': {
- 'type': 'bool'
- },
- 'fin': {
- 'type': 'bool'
- },
- 'psh': {
- 'type': 'bool'
- },
- 'rst': {
- 'type': 'bool'
- },
- 'syn': {
- 'type': 'bool'
- },
- 'urg': {
- 'type': 'bool'
- }
- },
- 'type': 'dict'
- },
- 'udp': {
- 'type': 'bool'
- }
- }
- },
- 'dscp': {
- 'type': 'str'
- },
- 'fragments': {
- 'type': 'str'
- },
- 'log': {
- 'type': 'str'
- },
- 'log_input': {
- 'type': 'str'
- },
- 'option': {
- 'type': 'dict',
- 'options': {
- 'add_ext': {
- 'type': 'bool'
- },
- 'any_options': {
- 'type': 'bool'
- },
- 'com_security': {
- 'type': 'bool'
- },
- 'dps': {
- 'type': 'bool'
- },
- 'encode': {
- 'type': 'bool'
- },
- 'eool': {
- 'type': 'bool'
- },
- 'ext_ip': {
- 'type': 'bool'
- },
- 'ext_security': {
- 'type': 'bool'
- },
- 'finn': {
- 'type': 'bool'
- },
- 'imitd': {
- 'type': 'bool'
- },
- 'lsr': {
- 'type': 'bool'
- },
- 'mtup': {
- 'type': 'bool'
- },
- 'mtur': {
- 'type': 'bool'
- },
- 'no_op': {
- 'type': 'bool'
- },
- 'nsapa': {
- 'type': 'bool'
- },
- 'record_route': {
- 'type': 'bool'
- },
- 'router_alert': {
- 'type': 'bool'
- },
- 'sdb': {
- 'type': 'bool'
- },
- 'security': {
- 'type': 'bool'
- },
- 'ssr': {
- 'type': 'bool'
- },
- 'stream_id': {
- 'type': 'bool'
- },
- 'timestamp': {
- 'type': 'bool'
- },
- 'traceroute': {
- 'type': 'bool'
- },
- 'ump': {
- 'type': 'bool'
- },
- 'visa': {
- 'type': 'bool'
- },
- 'zsu': {
- 'type': 'bool'
- }
- }
- },
- 'precedence': {
- 'type': 'int'
- },
- 'time_range': {
- 'type': 'str'
- },
- 'tos': {
- 'type': 'dict',
- 'options': {
- 'service_value': {
- 'type': 'int'
- },
- 'max_reliability': {
- 'type': 'bool'
- },
- 'max_throughput': {
- 'type': 'bool'
- },
- 'min_delay': {
- 'type': 'bool'
- },
- 'min_monetary_cost': {
- 'type': 'bool'
- },
- 'normal': {
- 'type': 'bool'
- }
- }
- },
- 'ttl': {
- 'type': 'dict',
- 'options': {
- 'eq': {
- 'type': 'int'
- },
- 'gt': {
- 'type': 'int'
- },
- 'lt': {
- 'type': 'int'
- },
- 'neq': {
- 'type': 'int'
- },
- 'range': {
- 'type': 'dict',
- 'options': {
- 'start': {
- 'type': 'int'
- },
- 'end': {
- 'type': 'int'
- }
- }
- }
- }
- },
- }
- }
- }
- },
- },
- 'type': 'list'
- },
- 'running_config': {
- 'type': 'str'
- },
- 'state': {
- 'choices': [
- 'merged', 'replaced', 'overridden', 'deleted', 'gathered',
- 'rendered', 'parsed'
- ],
- 'default':
- 'merged',
- 'type':
- 'str'
- }
- }
diff --git a/lib/ansible/module_utils/network/ios/argspec/facts/facts.py b/lib/ansible/module_utils/network/ios/argspec/facts/facts.py
deleted file mode 100644
index 8cac9e9827..0000000000
--- a/lib/ansible/module_utils/network/ios/argspec/facts/facts.py
+++ /dev/null
@@ -1,24 +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 ios facts module.
-"""
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-class FactsArgs(object):
- """ The arg spec for the ios 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/ios/argspec/interfaces/interfaces.py b/lib/ansible/module_utils/network/ios/argspec/interfaces/interfaces.py
deleted file mode 100644
index ae097f5307..0000000000
--- a/lib/ansible/module_utils/network/ios/argspec/interfaces/interfaces.py
+++ /dev/null
@@ -1,47 +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 ios_interfaces module
-"""
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-class InterfacesArgs(object):
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {'config': {'elements': 'dict',
- 'options': {'name': {'type': 'str', 'required': True},
- 'description': {'type': 'str'},
- 'enabled': {'default': True, 'type': 'bool'},
- 'speed': {'type': 'str'},
- 'mtu': {'type': 'int'},
- 'duplex': {'type': 'str', 'choices': ['full', 'half', 'auto']}},
- 'type': 'list'},
- 'state': {'choices': ['merged', 'replaced', 'overridden', 'deleted'],
- 'default': 'merged',
- 'type': 'str'}}
diff --git a/lib/ansible/module_utils/network/ios/argspec/l2_interfaces/l2_interfaces.py b/lib/ansible/module_utils/network/ios/argspec/l2_interfaces/l2_interfaces.py
deleted file mode 100644
index 5ef51fa23d..0000000000
--- a/lib/ansible/module_utils/network/ios/argspec/l2_interfaces/l2_interfaces.py
+++ /dev/null
@@ -1,57 +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 ios_l2_interfaces module
-"""
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-class L2_InterfacesArgs(object):
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {'config': {'elements': 'dict',
- 'options': {'name': {'type': 'str', 'required': True},
- 'mode': {'type': 'str', 'choices': ['access', 'trunk']},
- 'access': {'type': 'dict',
- 'options': {'vlan': {'type': 'int'}}
- },
- 'voice': {'type': 'dict',
- 'options': {'vlan': {'type': 'int'}}
- },
- 'trunk': {'type': 'dict',
- 'options': {'allowed_vlans': {'type': 'list'},
- 'encapsulation': {'type': 'str',
- 'choices':
- ['dot1q', 'isl', 'negotiate']},
- 'native_vlan': {'type': 'int'},
- 'pruning_vlans': {'type': 'list'}}
- }},
- 'type': 'list'},
- 'state': {'choices': ['merged', 'replaced', 'overridden', 'deleted'],
- 'default': 'merged',
- 'type': 'str'}}
diff --git a/lib/ansible/module_utils/network/ios/argspec/l3_interfaces/l3_interfaces.py b/lib/ansible/module_utils/network/ios/argspec/l3_interfaces/l3_interfaces.py
deleted file mode 100644
index cdf209a27a..0000000000
--- a/lib/ansible/module_utils/network/ios/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 ios_l3_interfaces module
-"""
-
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-class L3_InterfacesArgs(object):
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {'config': {'elements': 'dict',
- 'options': {'name': {'type': 'str', 'required': True},
- 'ipv4': {'element': 'dict',
- 'type': 'list',
- 'options': {'address': {'type': 'str'},
- 'secondary': {'type': 'bool'},
- 'dhcp_client': {'type': 'int'},
- 'dhcp_hostname': {'type': 'str'}}},
- 'ipv6': {'element': 'dict',
- 'type': 'list',
- 'options': {'address': {'type': 'str'}}}
- },
- 'type': 'list'},
- 'state': {'choices': ['merged', 'replaced', 'overridden', 'deleted'],
- 'default': 'merged',
- 'type': 'str'}}
diff --git a/lib/ansible/module_utils/network/ios/argspec/lacp/lacp.py b/lib/ansible/module_utils/network/ios/argspec/lacp/lacp.py
deleted file mode 100644
index 1e7294bc5c..0000000000
--- a/lib/ansible/module_utils/network/ios/argspec/lacp/lacp.py
+++ /dev/null
@@ -1,47 +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 ios_lacp module
-"""
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-class LacpArgs(object):
- """The arg spec for the ios_lacp module
- """
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- 'config': {'options': {'system': {'options': {'priority': {'required': True, 'type': 'int'}},
- 'type': 'dict'}
- }, 'type': 'dict'
- },
- 'state': {'choices': ['merged', 'replaced', 'deleted'], 'default': 'merged',
- 'type': 'str'}
- }
diff --git a/lib/ansible/module_utils/network/ios/argspec/lacp_interfaces/lacp_interfaces.py b/lib/ansible/module_utils/network/ios/argspec/lacp_interfaces/lacp_interfaces.py
deleted file mode 100644
index 10b17e5635..0000000000
--- a/lib/ansible/module_utils/network/ios/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 ios_lacp_interfaces module
-"""
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-class Lacp_InterfacesArgs(object):
- """The arg spec for the ios_lacp_interfaces module
- """
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {'config': {'elements': 'dict',
- 'options': {'name': {'required': True, 'type': 'str'},
- 'port_priority': {'type': 'int'},
- 'fast_switchover': {'type': 'bool'},
- 'max_bundle': {'type': 'int'}},
- 'type': 'list'},
- 'state': {'choices': ['merged', 'replaced', 'overridden', 'deleted'],
- 'default': 'merged',
- 'type': 'str'}}
diff --git a/lib/ansible/module_utils/network/ios/argspec/lag_interfaces/lag_interfaces.py b/lib/ansible/module_utils/network/ios/argspec/lag_interfaces/lag_interfaces.py
deleted file mode 100644
index 0f9b7e2535..0000000000
--- a/lib/ansible/module_utils/network/ios/argspec/lag_interfaces/lag_interfaces.py
+++ /dev/null
@@ -1,52 +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 ios_lag_interfaces module
-"""
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-class Lag_interfacesArgs(object):
-
- 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': ['auto', 'on', 'desirable',
- 'active', 'passive'],
- 'type': 'str', 'required': True},
- 'link': {'type': 'int'}
- },
- 'type': 'list'}},
- 'type': 'list'},
- 'state': {'choices': ['merged', 'replaced', 'overridden', 'deleted'],
- 'default': 'merged',
- 'type': 'str'}}
diff --git a/lib/ansible/module_utils/network/ios/argspec/lldp_global/lldp_global.py b/lib/ansible/module_utils/network/ios/argspec/lldp_global/lldp_global.py
deleted file mode 100644
index 62630036c2..0000000000
--- a/lib/ansible/module_utils/network/ios/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 ios_lldp_global module
-"""
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-class Lldp_globalArgs(object):
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {'config': {'options': {'holdtime': {'type': 'int'},
- 'reinit': {'type': 'int'},
- 'enabled': {'type': 'bool'},
- 'timer': {'type': 'int'},
- 'tlv_select': {
- 'options': {
- 'four_wire_power_management': {'type': 'bool'},
- 'mac_phy_cfg': {'type': 'bool'},
- 'management_address': {'type': 'bool'},
- 'port_description': {'type': 'bool'},
- 'port_vlan': {'type': 'bool'},
- 'power_management': {'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/ios/argspec/lldp_interfaces/lldp_interfaces.py b/lib/ansible/module_utils/network/ios/argspec/lldp_interfaces/lldp_interfaces.py
deleted file mode 100644
index 45af268d4d..0000000000
--- a/lib/ansible/module_utils/network/ios/argspec/lldp_interfaces/lldp_interfaces.py
+++ /dev/null
@@ -1,52 +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 ios_lldp_interfaces module
-"""
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-class Lldp_InterfacesArgs(object):
- """The arg spec for the ios_lldp_interfaces module
- """
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {'config': {'elements': 'dict',
- 'options': {'name': {'required': True, 'type': 'str'},
- 'transmit': {'type': 'bool'},
- 'receive': {'type': 'bool'},
- 'med_tlv_select': {'options': {'inventory_management': {'type': 'bool'}},
- 'type': 'dict'},
- 'tlv_select': {'options': {'power_management': {'type': 'bool'}},
- 'type': 'dict'}
- },
- 'type': 'list'},
- 'state': {'choices': ['merged', 'replaced', 'overridden', 'deleted'],
- 'default': 'merged',
- 'type': 'str'}}
diff --git a/lib/ansible/module_utils/network/ios/argspec/static_routes/static_routes.py b/lib/ansible/module_utils/network/ios/argspec/static_routes/static_routes.py
deleted file mode 100644
index 3362187987..0000000000
--- a/lib/ansible/module_utils/network/ios/argspec/static_routes/static_routes.py
+++ /dev/null
@@ -1,85 +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 ios_static_routes module
-"""
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-class Static_RoutesArgs(object):
- """The arg spec for the ios_static_routes module
- """
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- 'config': {
- 'elements': 'dict',
- 'options': {
- 'vrf': {'type': 'str'},
- 'address_families': {
- 'elements': 'dict',
- 'type': 'list',
- 'options': {
- 'afi': {'required': True, 'choices': ['ipv4', 'ipv6'], 'type': 'str'},
- 'routes': {
- 'elements': 'dict',
- 'type': 'list',
- 'options': {
- 'dest': {'required': True, 'type': 'str'},
- 'topology': {'type': 'str'},
- 'next_hops': {
- 'elements': 'dict',
- 'type': 'list',
- 'options': {
- 'forward_router_address': {'type': 'str'},
- 'interface': {'type': 'str'},
- 'dhcp': {'type': 'bool'},
- 'distance_metric': {'type': 'int'},
- 'global': {'type': 'bool'},
- 'name': {'type': 'str'},
- 'multicast': {'type': 'bool'},
- 'permanent': {'type': 'bool'},
- 'tag': {'type': 'int'},
- 'track': {'type': 'int'}
- }
- }
- }
- }
- }
- }
- },
- 'type': 'list'
- },
- 'running_config': {'type': 'str'},
- 'state': {
- 'choices': ['merged', 'replaced', 'overridden', 'deleted', 'gathered', 'rendered', 'parsed'],
- 'default': 'merged',
- 'type': 'str'
- }
- }
diff --git a/lib/ansible/module_utils/network/ios/argspec/vlans/vlans.py b/lib/ansible/module_utils/network/ios/argspec/vlans/vlans.py
deleted file mode 100644
index 893904cfe7..0000000000
--- a/lib/ansible/module_utils/network/ios/argspec/vlans/vlans.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 ios_vlans module
-"""
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-class VlansArgs(object):
- """The arg spec for the ios_vlans module
- """
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {'config': {'elements': 'dict',
- 'options': {'name': {'type': 'str'},
- 'vlan_id': {'required': True, 'type': 'int'},
- 'mtu': {'type': 'int'},
- 'remote_span': {'type': 'bool'},
- 'state': {'type': 'str', 'choices': ['active', 'suspend']},
- 'shutdown': {'type': 'str', 'choices': ['enabled', 'disabled']}},
- 'type': 'list'},
- 'state': {'choices': ['merged', 'replaced', 'overridden', 'deleted'],
- 'default': 'merged',
- 'type': 'str'}}
diff --git a/lib/ansible/module_utils/network/ios/config/acl_interfaces/acl_interfaces.py b/lib/ansible/module_utils/network/ios/config/acl_interfaces/acl_interfaces.py
deleted file mode 100644
index fa3352389c..0000000000
--- a/lib/ansible/module_utils/network/ios/config/acl_interfaces/acl_interfaces.py
+++ /dev/null
@@ -1,405 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat Inc.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-The ios_acl_interfaces class
-It is in this file where the current configuration (as dict)
-is compared to the provided configuration (as dict) and the command set
-necessary to bring the current configuration to it's desired end-state is
-created
-"""
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-from ansible.module_utils.network.common.cfg.base import ConfigBase
-from ansible.module_utils.network.common.utils import to_list
-from ansible.module_utils.network.ios.facts.facts import Facts
-from ansible.module_utils.six import iteritems
-from ansible.module_utils.network.ios.utils.utils import remove_duplicate_interface, normalize_interface
-
-
-class Acl_Interfaces(ConfigBase):
- """
- The ios_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 moduel execution
- """
- result = {'changed': False}
- commands = list()
- warnings = list()
-
- 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)
- 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':
- running_config = self._module.params['running_config']
- if not running_config:
- self._module.fail_json(
- msg="value of running_config parameter must not be empty for state parsed"
- )
- result['parsed'] = self.get_acl_interfaces_facts(data=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 deisred configuration
- """
- want = self._module.params['config']
- if want:
- for item in want:
- item['name'] = normalize_interface(item['name'])
-
- 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 deisred configuration
- """
- commands = []
-
- state = self._module.params['state']
- if state in ('overridden', 'merged', 'replaced', 'rendered') and not want:
- self._module.fail_json(msg='value of config parameter must not be empty for state {0}'.format(state))
-
- if state == 'overridden':
- commands = self._state_overridden(want, have)
- elif state == 'deleted':
- commands = self._state_deleted(want, have)
- elif state == 'merged' or 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
- :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 deisred configuration
- """
- commands = []
-
- for interface in want:
- for each in have:
- if each['name'] == interface['name']:
- break
- else:
- continue
- commands.extend(self._clear_config(interface, each, 'replaced'))
- commands.extend(self._set_config(interface, each))
- # Remove the duplicate interface call
- commands = remove_duplicate_interface(commands)
-
- return commands
-
- def _state_overridden(self, want, have):
- """ The command generator when state is overridden
- :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 = []
-
- for each in have:
- for interface in want:
- if each['name'] == interface['name']:
- break
- else:
- # We didn't find a matching desired state, which means we can
- # pretend we recieved an empty desired state.
- interface = dict(name=each['name'])
- commands.extend(self._clear_config(interface, each))
- continue
- commands.extend(self._clear_config(interface, each, 'overridden'))
- commands.extend(self._set_config(interface, each))
- # Remove the duplicate interface call
- commands = remove_duplicate_interface(commands)
-
- return commands
-
- def _state_merged(self, want, have):
- """ The command generator when state is merged
- :param want: the additive configuration as a dictionary
- :param have: the current configuration as a dictionary
- :rtype: A list
- :returns: the commands necessary to merge the provided into
- the current configuration
- """
- commands = []
-
- for interface in want:
- for each in have:
- if each['name'] == interface['name']:
- break
- else:
- # configuring non-existing interface
- commands.extend(self._set_config(interface, dict()))
- continue
- commands.extend(self._set_config(interface, each))
-
- return commands
-
- def _state_deleted(self, want, have):
- """ The command generator when state is deleted
- :param want: the objects from which the configuration should be removed
- :param have: the current configuration as a dictionary
- :rtype: A list
- :returns: the commands necessary to remove the current configuration
- of the provided objects
- """
- commands = []
-
- if want:
- for interface in want:
- for each in have:
- if each['name'] == interface['name']:
- break
- else:
- continue
- commands.extend(self._clear_config(interface, each))
- else:
- for each in have:
- commands.extend(self._clear_config(dict(), each))
-
- return commands
-
- def dict_to_set(self, input_dict, test_set, final_set, count=0):
- # recursive function to convert input dict to set for comparision
- test_dict = dict()
- if isinstance(input_dict, dict):
- input_dict_len = len(input_dict)
- for k, v in sorted(iteritems(input_dict)):
- count += 1
- if isinstance(v, list):
- for each in v:
- if isinstance(each, dict):
- input_dict_len = len(each)
- if [True for i in each.values() if type(i) == list]:
- self.dict_to_set(each, set(), final_set, count)
- else:
- self.dict_to_set(each, test_set, final_set, 0)
- else:
- if v is not None:
- test_dict.update({k: v})
- if tuple(iteritems(test_dict)) not in test_set and count == input_dict_len:
- test_set.add(tuple(iteritems(test_dict)))
- count = 0
- if count == input_dict_len + 1:
- test_set.update(tuple(iteritems(test_dict)))
- final_set.add(tuple(test_set))
-
- def _set_config(self, want, have):
- """ Function that sets the acls config based on the want and have config
- :param want: want config
- :param have: have config
- :param acl_want: want acl config
- :param afi: acl afi type
- :rtype: A list
- :returns: the commands generated based on input want/have params
- """
- commands = []
-
- want_set = set()
- have_set = set()
- self.dict_to_set(want, set(), want_set)
- self.dict_to_set(have, set(), have_set)
-
- for w in want_set:
- want_afi = dict(w).get('afi')
- if have_set:
- def common_diff_config_code(diff_list, cmd, commands):
- for each in diff_list:
- try:
- temp = dict(each)
- temp_cmd = cmd + ' {0} {1}'.format(temp['name'], temp['direction'])
- if temp_cmd not in commands:
- commands.append(temp_cmd)
- except ValueError:
- continue
- for h in have_set:
- have_afi = dict(h).get('afi')
- if have_afi == want_afi:
- if want_afi == 'ipv4':
- diff = set(w) - set(h)
- if diff:
- cmd = 'ip access-group'
- common_diff_config_code(diff, cmd, commands)
- if want_afi == 'ipv6':
- diff = set(w) - set(h)
- if diff:
- cmd = 'ipv6 traffic-filter'
- common_diff_config_code(diff, cmd, commands)
- break
- else:
- if want_afi == 'ipv4':
- diff = set(w) - set(h)
- if diff:
- cmd = 'ip access-group'
- common_diff_config_code(diff, cmd, commands)
- if want_afi == 'ipv6':
- diff = set(w) - set(h)
- if diff:
- cmd = 'ipv6 traffic-filter'
- common_diff_config_code(diff, cmd, commands)
- else:
- def common_want_config_code(want, cmd, commands):
- for each in want:
- if each[0] == 'afi':
- continue
- temp = dict(each)
- temp_cmd = cmd + ' {0} {1}'.format(temp['name'], temp['direction'])
- commands.append(temp_cmd)
- if want_afi == 'ipv4':
- cmd = 'ip access-group'
- common_want_config_code(w, cmd, commands)
- if want_afi == 'ipv6':
- cmd = 'ipv6 traffic-filter'
- common_want_config_code(w, cmd, commands)
- commands.sort()
- if commands:
- interface = want.get('name')
- commands.insert(0, 'interface {0}'.format(interface))
-
- return commands
-
- def _clear_config(self, want, have, state=''):
- """ Function that deletes the acl config based on the want and have config
- :param acl: acl config
- :param config: config
- :rtype: A list
- :returns: the commands generated based on input acl/config params
- """
- commands = []
-
- if want.get('name'):
- interface = 'interface ' + want['name']
- else:
- interface = 'interface ' + have['name']
-
- w_access_group = want.get('access_groups')
- temp_want_afi = []
- temp_want_acl_name = []
- if w_access_group:
- # get the user input afi and acls
- for each in w_access_group:
- want_afi = each.get('afi')
- want_acls = each.get('acls')
- if want_afi:
- temp_want_afi.append(want_afi)
- if want_acls:
- for each in want_acls:
- temp_want_acl_name.append(each.get('name'))
-
- h_access_group = have.get('access_groups')
- if h_access_group:
- for access_grp in h_access_group:
- for acl in access_grp.get('acls'):
- have_afi = access_grp.get('afi')
- acl_name = acl.get('name')
- acl_direction = acl.get('direction')
- if temp_want_afi and state not in ['replaced', 'overridden']:
- # if user want to delete acls based on afi
- if 'ipv4' in temp_want_afi and have_afi == 'ipv4':
- if acl_name in temp_want_acl_name:
- continue
- cmd = 'no ip access-group'
- cmd += ' {0} {1}'.format(acl_name, acl_direction)
- commands.append(cmd)
- if 'ipv6' in temp_want_afi and have_afi == 'ipv6':
- if acl_name in temp_want_acl_name:
- continue
- cmd = 'no ipv6 traffic-filter'
- cmd += ' {0} {1}'.format(acl_name, acl_direction)
- commands.append(cmd)
- else:
- # if user want to delete acls based on interface
- if access_grp.get('afi') == 'ipv4':
- if acl_name in temp_want_acl_name:
- continue
- cmd = 'no ip access-group'
- cmd += ' {0} {1}'.format(acl_name, acl_direction)
- commands.append(cmd)
- elif access_grp.get('afi') == 'ipv6':
- if acl_name in temp_want_acl_name:
- continue
- cmd = 'no ipv6 traffic-filter'
- cmd += ' {0} {1}'.format(acl_name, acl_direction)
- commands.append(cmd)
- if commands:
- # inserting the interface at first
- commands.insert(0, interface)
-
- return commands
diff --git a/lib/ansible/module_utils/network/ios/config/acls/acls.py b/lib/ansible/module_utils/network/ios/config/acls/acls.py
deleted file mode 100644
index 2a3f3f244b..0000000000
--- a/lib/ansible/module_utils/network/ios/config/acls/acls.py
+++ /dev/null
@@ -1,717 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat Inc.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-The ios_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 copy
-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.ios.facts.facts import Facts
-from ansible.module_utils.six import iteritems
-from ansible.module_utils.network.common.utils import remove_empties
-from ansible.module_utils.network.ios.utils.utils import new_dict_to_set
-
-
-class Acls(ConfigBase):
- """
- The ios_acls class
- """
-
- gather_subset = [
- '!all',
- '!min',
- ]
-
- gather_network_resources = [
- 'acls',
- ]
-
- def __init__(self, module):
- super(Acls, self).__init__(module)
-
- def get_acl_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_facts = facts['ansible_network_resources'].get('acls')
- if not acl_facts:
- return []
-
- return acl_facts
-
- def execute_module(self):
- """ Execute the module
-
- :rtype: A dictionary
- :returns: The result from moduel execution
- """
- result = {'changed': False}
- commands = list()
- warnings = list()
-
- if self.state in self.ACTION_STATES:
- existing_acl_facts = self.get_acl_facts()
- else:
- existing_acl_facts = []
-
- if self.state in self.ACTION_STATES or self.state == 'rendered':
- commands.extend(self.set_config(existing_acl_facts))
-
- if commands and self.state in self.ACTION_STATES:
- if not self._module.check_mode:
- self._connection.edit_config(commands)
- result['changed'] = True
-
- if self.state in self.ACTION_STATES:
- result['commands'] = commands
-
- if self.state in self.ACTION_STATES or self.state == 'gathered':
- changed_acl_facts = self.get_acl_facts()
- elif self.state == 'rendered':
- result['rendered'] = commands
- elif self.state == 'parsed':
- running_config = self._module.params['running_config']
- if not running_config:
- self._module.fail_json(msg="value of running_config parameter must not be empty for state parsed")
- result['parsed'] = self.get_acl_facts(data=running_config)
- else:
- changed_acl_facts = []
-
- if self.state in self.ACTION_STATES:
- result['before'] = existing_acl_facts
- if result['changed']:
- result['after'] = changed_acl_facts
- elif self.state == 'gathered':
- result['gathered'] = changed_acl_facts
-
- result['warnings'] = warnings
-
- return result
-
- def set_config(self, existing_acl_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 deisred configuration
- """
- want = self._module.params['config']
- have = existing_acl_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 deisred configuration
- """
- commands = []
-
- state = self._module.params['state']
- if state in ('overridden', 'merged', 'replaced', 'rendered') and not want:
- self._module.fail_json(msg='value of config parameter must not be empty for state {0}'.format(state))
-
- if state == 'overridden':
- commands = self._state_overridden(want, have)
- elif state == 'deleted':
- commands = self._state_deleted(want, have)
- elif state == 'merged' or 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
-
- :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 deisred configuration
- """
- commands = []
-
- for config_want in want:
- for acls_want in config_want.get('acls'):
- for ace_want in acls_want.get('aces'):
- check = False
- for config_have in have:
- for acls_have in config_have.get('acls'):
- for ace_have in acls_have.get('aces'):
- if acls_want.get('name') == acls_have.get('name'):
- ace_want = remove_empties(ace_want)
- acls_want = remove_empties(acls_want)
- cmd, change = self._set_config(ace_want,
- ace_have,
- acls_want,
- config_want['afi'])
- if cmd:
- for temp_acls_have in config_have.get('acls'):
- for temp_ace_have in temp_acls_have.get('aces'):
- if acls_want.get('name') == temp_acls_have.get('name'):
- commands.extend(
- self._clear_config(temp_acls_have,
- config_have,
- temp_ace_have.get('sequence')))
- commands.extend(cmd)
- check = True
- if check:
- break
- if check:
- break
- if not check:
- # For configuring any non-existing want config
- ace_want = remove_empties(ace_want)
- cmd, change = self._set_config(ace_want,
- {},
- acls_want,
- config_want['afi'])
- commands.extend(cmd)
- # Split and arrange the config commands
- commands = self.split_set_cmd(commands)
-
- return commands
-
- def _state_overridden(self, want, have):
- """ The command generator when state is overridden
- :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 = []
- # Creating a copy of want, so that want dict is intact even after delete operation
- # performed during override want n have comparison
- temp_want = copy.deepcopy(want)
-
- for config_have in have:
- for acls_have in config_have.get('acls'):
- for ace_have in acls_have.get('aces'):
- check = False
- for config_want in temp_want:
- count = 0
- for acls_want in config_want.get('acls'):
- for ace_want in acls_want.get('aces'):
- if acls_want.get('name') == acls_have.get('name'):
- ace_want = remove_empties(ace_want)
- acls_want = remove_empties(acls_want)
- cmd, change = self._set_config(ace_want, ace_have, acls_want, config_want['afi'])
- if cmd:
- for temp_acls_have in config_have.get('acls'):
- for temp_ace_have in temp_acls_have.get('aces'):
- if acls_want.get('name') == temp_acls_have.get('name'):
- commands.extend(
- self._clear_config(temp_acls_have,
- config_have,
- temp_ace_have.get('sequence')))
- commands.extend(cmd)
- check = True
- if check:
- del config_want.get('acls')[count]
- else:
- count += 1
- if check:
- break
- if check:
- break
- if not check:
- # Delete the config not present in want config
- commands.extend(self._clear_config(acls_have, config_have))
-
- # For configuring any non-existing want config
- for config_want in temp_want:
- for acls_want in config_want.get('acls'):
- for ace_want in acls_want.get('aces'):
- ace_want = remove_empties(ace_want)
- cmd, change = self._set_config(ace_want,
- {},
- acls_want,
- config_want['afi'])
- commands.extend(cmd)
-
- # Split and arrange the config commands
- commands = self.split_set_cmd(commands)
- # Arranging the cmds suct that all delete cmds are fired before all set cmds
- negate_commands = [each for each in commands if 'no' in each and 'access-list' in each]
- negate_commands.extend([each for each in commands if each not in negate_commands])
- commands = negate_commands
-
- return commands
-
- def _state_merged(self, want, have):
- """ The command generator when state is merged
-
- :param want: the additive configuration as a dictionary
- :param have: the current configuration as a dictionary
- :rtype: A list
- :returns: the commands necessary to merge the provided into
- the current configuration
- """
- commands = []
-
- for config_want in want:
- for acls_want in config_want.get('acls'):
- for ace_want in acls_want.get('aces'):
- check = False
- for config_have in have:
- for acls_have in config_have.get('acls'):
- for ace_have in acls_have.get('aces'):
- if acls_want.get('name') == acls_have.get('name') and \
- ace_want.get('sequence') == ace_have.get('sequence'):
- ace_want = remove_empties(ace_want)
- cmd, change = self._set_config(ace_want,
- ace_have,
- acls_want,
- config_want['afi'])
- # clear config will be fired only when there's command wrt to config
- if config_want.get('afi') == 'ipv4' and change:
- # for ipv4 only inplace update cannot be done, so deleting the sequence ace
- # and then updating the want ace changes
- commands.extend(self._clear_config(acls_want,
- config_want,
- ace_want.get('sequence')))
- commands.extend(cmd)
- check = True
- elif acls_want.get('name') == acls_have.get('name'):
- ace_want = remove_empties(ace_want)
- cmd, check = self.common_condition_check(ace_want,
- ace_have,
- acls_want,
- config_want,
- check,
- acls_have)
- if acls_have.get('acl_type') == 'standard':
- check = True
- commands.extend(cmd)
- if check:
- break
- if check:
- break
- if not check:
- # For configuring any non-existing want config
- ace_want = remove_empties(ace_want)
- cmd, change = self._set_config(ace_want,
- {},
- acls_want,
- config_want['afi'])
- commands.extend(cmd)
- # Split and arrange the config commands
- commands = self.split_set_cmd(commands)
-
- return commands
-
- def _state_deleted(self, want, have):
- """ The command generator when state is deleted
-
- :param want: the objects from which the configuration should be removed
- :param have: the current configuration as a dictionary
- :rtype: A list
- :returns: the commands necessary to remove the current configuration
- of the provided objects
- """
- commands = []
- if want:
- for config_want in want:
- if config_want.get('acls'):
- for acls_want in config_want.get('acls'):
- if acls_want.get('aces'):
- for ace_want in acls_want.get('aces'):
- for config_have in have:
- for acls_have in config_have.get('acls'):
- if acls_want.get('name') == acls_have.get('name'):
- if ace_want.get('sequence'):
- commands.extend(self._clear_config(acls_want,
- config_want,
- ace_want.get('sequence')))
- else:
- commands.extend(self._clear_config(acls_want,
- config_want))
- else:
- for config_have in have:
- for acls_have in config_have.get('acls'):
- if acls_want.get('name') == acls_have.get('name'):
- commands.extend(self._clear_config(acls_want,
- config_want))
- else:
- afi_want = config_want.get('afi')
- for config_have in have:
- if config_have.get('afi') == afi_want:
- for acls_have in config_have.get('acls'):
- commands.extend(self._clear_config(acls_have, config_want))
- # Split and arrange the config commands
- commands = self.split_set_cmd(commands)
- else:
- for config_have in have:
- for acls_have in config_have.get('acls'):
- commands.extend(self._clear_config(acls_have, config_have))
-
- return commands
-
- def common_condition_check(self, want, have, acls_want, config_want, check, state='', acls_have=None):
- """ The command formatter from the generated command
- :param want: want config
- :param have: have config
- :param acls_want: acls want config
- :param config_want: want config list
- :param check: for same acls in want and have config, check=True
- :param state: operation state
- :rtype: A list
- :returns: commands generated from want n have config diff
- """
- commands = []
-
- if want.get('source') and want.get('destination') and have.get('source') and have.get('destination'):
- if want.get('destination') and have.get('destination') or \
- want.get('source').get('address') and have.get('source'):
- if want.get('destination').get('address') == \
- have.get('destination').get('address') and \
- want.get('source').get('address') == \
- have.get('source').get('address'):
- cmd, change = self._set_config(want,
- have,
- acls_want,
- config_want['afi'])
- commands.extend(cmd)
- check = True
- if commands:
- if state == 'replaced' or state == 'overridden':
- commands.extend(self._clear_config(acls_want, config_want))
- elif want.get('destination').get('any') == \
- have.get('destination').get('any') and \
- want.get('source').get('address') == \
- have.get('source').get('address') and \
- want.get('destination').get('any'):
- cmd, change = self._set_config(want,
- have,
- acls_want,
- config_want['afi'])
- commands.extend(cmd)
- check = True
- if commands:
- if state == 'replaced' or state == 'overridden':
- commands.extend(self._clear_config(acls_want, config_want))
- elif want.get('destination').get('address') == \
- have.get('destination').get('address') and \
- want.get('source').get('any') == have.get('source').get('any') and \
- want.get('source').get('any'):
- cmd, change = self._set_config(want,
- have,
- acls_want,
- config_want['afi'])
- commands.extend(cmd)
- check = True
- if commands:
- if state == 'replaced' or state == 'overridden':
- commands.extend(self._clear_config(acls_want, config_want))
- elif want.get('destination').get('any') == \
- have.get('destination').get('any') and \
- want.get('source').get('any') == have.get('source').get('any') and \
- want.get('destination').get('any'):
- cmd, change = self._set_config(want,
- have,
- acls_want,
- config_want['afi'])
- commands.extend(cmd)
- check = True
- if commands:
- if state == 'replaced' or state == 'overridden':
- commands.extend(self._clear_config(acls_want, config_want))
- elif acls_have and acls_have.get('acl_type') == 'standard':
- check = True
- if want.get('source') == have.get('source'):
- cmd, change = self._set_config(want,
- have,
- acls_want,
- config_want['afi'])
- commands.extend(cmd)
-
- return commands, check
-
- def split_set_cmd(self, cmds):
- """ The command formatter from the generated command
- :param cmds: generated command
- :rtype: A list
- :returns: the formatted commands which is compliant and
- actually fired on the device
- """
- command = []
-
- def common_code(access_grant, cmd, command):
- cmd = cmd.split(access_grant)
- access_list = cmd[0].strip(' ')
- if access_list not in command:
- command.append(access_list)
- command_items = len(command)
- # get the last index of the list and push the trimmed cmd at the end of list
- index = command.index(access_list) + (command_items - command.index(access_list))
- cmd = access_grant + cmd[1]
- command.insert(index + 1, cmd)
-
- def sequence_common_code(sequence_index, each_list, command):
- # Command to split
- def join_list_to_str(temp_list, cmd=''):
- for item in temp_list:
- cmd += item
- cmd += ' '
- return cmd
-
- temp_list = each_list[:sequence_index]
- cmd = join_list_to_str(temp_list).rstrip(' ')
- if cmd not in command:
- command.append(cmd)
- temp_list = each_list[sequence_index:]
- cmd = join_list_to_str(temp_list).rstrip(' ')
- command.append(cmd)
-
- def grant_common_code(cmd_list, grant_type, command):
- index = cmd_list.index(grant_type)
- if 'extended' in each_list:
- if cmd_list.index('extended') == (index - 2):
- common_code(grant_type, each, command)
- else:
- sequence_common_code((index - 1), each_list, command)
- elif 'standard' in each_list:
- if cmd_list.index('standard') == (index - 2):
- common_code(grant_type, each, command)
- else:
- sequence_common_code((index - 1), each_list, command)
- elif 'ipv6' in each_list:
- if 'sequence' in each_list:
- sequence_index = each_list.index('sequence')
- sequence_common_code(sequence_index, each_list, command)
- else:
- common_code(grant_type, each, command)
- return command
-
- for each in cmds:
- each_list = each.split(' ')
- if 'no' in each:
- if each_list.index('no') == 0:
- command.append(each)
- else:
- common_code('no', each, command)
- if 'deny' in each:
- grant_common_code(each_list, 'deny', command)
- if 'permit' in each:
- grant_common_code(each_list, 'permit', command)
-
- return command
-
- def source_dest_config(self, config, cmd, protocol_option):
- """ Function to populate source/destination address and port protocol options
- :param config: want and have diff config
- :param cmd: source/destination command
- :param protocol_option: source/destination protocol option
- :rtype: A list
- :returns: the commands generated based on input source/destination params
- """
- if 'ipv6' in cmd:
- address = config.get('address')
- host = config.get('host')
- if (address and '::' not in address) or (host and '::' not in host):
- self._module.fail_json(msg='Incorrect IPV6 address!')
- else:
- address = config.get('address')
- wildcard = config.get('wildcard_bits')
- host = config.get('host')
- any = config.get('any')
- if 'standard' in cmd and address and not wildcard:
- cmd = cmd + ' {0}'.format(address)
- elif address and wildcard:
- cmd = cmd + ' {0} {1}'.format(address, wildcard)
- elif host:
- cmd = cmd + ' host {0}'.format(host)
- if any:
- cmd = cmd + ' {0}'.format('any')
- port_protocol = config.get('port_protocol')
- if port_protocol and (protocol_option.get('tcp') or protocol_option.get('udp')):
- cmd = cmd + ' {0} {1}'.format(list(port_protocol)[0], list(port_protocol.values())[0])
- elif port_protocol and not (protocol_option.get('tcp') or protocol_option.get('udp')):
- self._module.fail_json(msg='Port Protocol option is valid only with TCP/UDP Protocol option!')
-
- return cmd
-
- def _set_config(self, want, have, acl_want, afi):
- """ Function that sets the acls config based on the want and have config
- :param want: want config
- :param have: have config
- :param acl_want: want acls config
- :param afi: acls afi type
- :rtype: A list
- :returns: the commands generated based on input want/have params
- """
- commands = []
- change = False
- want_set = set()
- have_set = set()
- # Convert the want and have dict to its respective set for taking the set diff
- new_dict_to_set(want, [], want_set)
- new_dict_to_set(have, [], have_set)
- diff = want_set - have_set
-
- # Populate the config only when there's a diff b/w want and have config
- if diff:
- name = acl_want.get('name')
- if afi == 'ipv4':
- try:
- name = int(name)
- # If name is numbered acls
- if name <= 99:
- cmd = 'ip access-list standard {0}'.format(name)
- elif name >= 100:
- cmd = 'ip access-list extended {0}'.format(name)
- except ValueError:
- # If name is named acls
- acl_type = acl_want.get('acl_type')
- if acl_type:
- cmd = 'ip access-list {0} {1}'.format(acl_type, name)
- else:
- self._module.fail_json(msg='ACL type value is required for Named ACL!')
-
- elif afi == 'ipv6':
- cmd = 'ipv6 access-list {0}'.format(name)
-
- # Get all of aces option values from diff dict
- sequence = want.get('sequence')
- grant = want.get('grant')
- source = want.get('source')
- destination = want.get('destination')
- po = want.get('protocol_options')
- protocol = want.get('protocol')
- dscp = want.get('dscp')
- fragments = want.get('fragments')
- log = want.get('log')
- log_input = want.get('log_input')
- option = want.get('option')
- precedence = want.get('precedence')
- time_range = want.get('time_range')
- tos = want.get('tos')
- ttl = want.get('ttl')
-
- if sequence:
- if afi == 'ipv6':
- cmd = cmd + ' sequence {0}'.format(sequence)
- else:
- cmd = cmd + ' {0}'.format(sequence)
- if grant:
- cmd = cmd + ' {0}'.format(grant)
- if po and isinstance(po, dict):
- po_key = list(po)[0]
- if protocol and protocol != po_key:
- self._module.fail_json(msg='Protocol value cannot be different from Protocol option protocol value!')
- cmd = cmd + ' {0}'.format(po_key)
- if po.get('icmp'):
- po_val = po.get('icmp')
- elif po.get('igmp'):
- po_val = po.get('igmp')
- elif po.get('tcp'):
- po_val = po.get('tcp')
- elif protocol:
- cmd = cmd + ' {0}'.format(protocol)
- if source:
- cmd = self.source_dest_config(source, cmd, po)
- if destination:
- cmd = self.source_dest_config(destination, cmd, po)
- if po:
- cmd = cmd + ' {0}'.format(list(po_val)[0])
- if dscp:
- cmd = cmd + ' dscp {0}'.format(dscp)
- if fragments:
- cmd = cmd + ' fragments {0}'.format(fragments)
- if log:
- cmd = cmd + ' log {0}'.format(log)
- if log_input:
- cmd = cmd + ' log-input {0}'.format(log_input)
- if option:
- cmd = cmd + ' option {0}'.format(list(option)[0])
- if precedence:
- cmd = cmd + ' precedence {0}'.format(precedence)
- if time_range:
- cmd = cmd + ' time-range {0}'.format(time_range)
- if tos:
- for k, v in iteritems(tos):
- if k == 'service_value':
- cmd = cmd + ' tos {0}'.format(v)
- else:
- cmd = cmd + ' tos {0}'.format(v)
- if ttl:
- for k, v in iteritems(ttl):
- if k == 'range' and v:
- start = v.get('start')
- end = v.get('start')
- cmd = cmd + ' ttl {0} {1}'.format(start, end)
- elif v:
- cmd = cmd + ' ttl {0} {1}'.format(k, v)
-
- commands.append(cmd)
- if commands:
- change = True
-
- return commands, change
-
- def _clear_config(self, acls, config, sequence=''):
- """ Function that deletes the acls config based on the want and have config
- :param acls: acls config
- :param config: config
- :rtype: A list
- :returns: the commands generated based on input acls/config params
- """
- commands = []
- afi = config.get('afi')
- name = acls.get('name')
- if afi == 'ipv4' and name:
- try:
- name = int(name)
- if name <= 99 and not sequence:
- cmd = 'no ip access-list standard {0}'.format(name)
- elif name >= 100 and not sequence:
- cmd = 'no ip access-list extended {0}'.format(name)
- elif sequence:
- if name <= 99:
- cmd = 'ip access-list standard {0} '.format(name)
- elif name >= 100:
- cmd = 'ip access-list extended {0} '.format(name)
- cmd += 'no {0}'.format(sequence)
- except ValueError:
- acl_type = acls.get('acl_type')
- if acl_type == 'extended' and not sequence:
- cmd = 'no ip access-list extended {0}'.format(name)
- elif acl_type == 'standard' and not sequence:
- cmd = 'no ip access-list standard {0}'.format(name)
- elif sequence:
- if acl_type == 'extended':
- cmd = 'ip access-list extended {0} '.format(name)
- elif acl_type == 'standard':
- cmd = 'ip access-list standard {0}'.format(name)
- cmd += 'no {0}'.format(sequence)
- else:
- self._module.fail_json(msg="ACL type value is required for Named ACL!")
- elif afi == 'ipv6' and name:
- if sequence:
- cmd = 'no sequence {0}'.format(sequence)
- else:
- cmd = 'no ipv6 access-list {0}'.format(name)
- commands.append(cmd)
-
- return commands
diff --git a/lib/ansible/module_utils/network/ios/config/interfaces/interfaces.py b/lib/ansible/module_utils/network/ios/config/interfaces/interfaces.py
deleted file mode 100644
index bcf817f4d8..0000000000
--- a/lib/ansible/module_utils/network/ios/config/interfaces/interfaces.py
+++ /dev/null
@@ -1,295 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat Inc.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-The ios_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
-from ansible.module_utils.network.ios.facts.facts import Facts
-from ansible.module_utils.network.ios.utils.utils import get_interface_type, dict_to_set
-from ansible.module_utils.network.ios.utils.utils import remove_command_from_config_list, add_command_to_config_list
-from ansible.module_utils.network.ios.utils.utils import filter_dict_having_none_value, remove_duplicate_interface
-
-
-class Interfaces(ConfigBase):
- """
- The ios_interfaces class
- """
-
- gather_subset = [
- '!all',
- '!min',
- ]
-
- gather_network_resources = [
- 'interfaces',
- ]
-
- params = ('description', 'mtu', 'speed', 'duplex')
-
- def __init__(self, module):
- super(Interfaces, self).__init__(module)
-
- def get_interfaces_facts(self):
- """ 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 moduel 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 deisred 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 deisred configuration
- """
- commands = []
-
- state = self._module.params['state']
- if state in ('overridden', 'merged', 'replaced') and not want:
- self._module.fail_json(msg='value of config parameter must not be empty for state {0}'.format(state))
-
- if state == 'overridden':
- commands = 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
-
- def _state_replaced(self, want, have):
- """ The command generator when state is replaced
-
- :param want: the desired configuration as a dictionary
- :param have: the current configuration as a dictionary
- :param interface_type: interface type
- :rtype: A list
- :returns: the commands necessary to migrate the current configuration
- to the deisred configuration
- """
- commands = []
-
- for interface in want:
- for each in have:
- if each['name'] == interface['name']:
- break
- elif interface['name'] in each['name']:
- break
- else:
- # configuring non-existing interface
- commands.extend(self._set_config(interface, dict()))
- continue
- have_dict = filter_dict_having_none_value(interface, each)
- commands.extend(self._clear_config(dict(), have_dict))
- commands.extend(self._set_config(interface, each))
- # Remove the duplicate interface call
- commands = remove_duplicate_interface(commands)
-
- return commands
-
- def _state_overridden(self, want, have):
- """ The command generator when state is overridden
-
- :param want: the desired configuration as a dictionary
- :param obj_in_have: the current configuration as a dictionary
- :rtype: A list
- :returns: the commands necessary to migrate the current configuration
- to the desired configuration
- """
- commands = []
-
- for each in have:
- for interface in want:
- count = 0
- if each['name'] == interface['name']:
- break
- elif interface['name'] in each['name']:
- break
- count += 1
- else:
- # We didn't find a matching desired state, which means we can
- # pretend we received an empty desired state.
- interface = dict(name=each['name'])
- commands.extend(self._clear_config(interface, each))
- continue
- have_dict = filter_dict_having_none_value(interface, each)
- commands.extend(self._clear_config(dict(), have_dict))
- commands.extend(self._set_config(interface, each))
- # as the pre-existing interface are now configured by
- # above set_config call, deleting the respective
- # interface entry from the want list
- del want[count]
-
- # Iterating through want list which now only have new interfaces to be
- # configured
- for each in want:
- commands.extend(self._set_config(each, dict()))
- # Remove the duplicate interface call
- commands = remove_duplicate_interface(commands)
-
- return commands
-
- def _state_merged(self, want, have):
- """ The command generator when state is merged
-
- :param want: the additive configuration as a dictionary
- :param obj_in_have: the current configuration as a dictionary
- :rtype: A list
- :returns: the commands necessary to merge the provided into
- the current configuration
- """
- commands = []
-
- for interface in want:
- for each in have:
- if each['name'] == interface['name']:
- break
- else:
- # configuring non-existing interface
- commands.extend(self._set_config(interface, dict()))
- continue
- commands.extend(self._set_config(interface, each))
-
- return commands
-
- def _state_deleted(self, want, have):
- """ The command generator when state is deleted
-
- :param want: the objects from which the configuration should be removed
- :param obj_in_have: the current configuration as a dictionary
- :param interface_type: interface type
- :rtype: A list
- :returns: the commands necessary to remove the current configuration
- of the provided objects
- """
- commands = []
-
- if want:
- for interface in want:
- for each in have:
- if each['name'] == interface['name']:
- break
- else:
- continue
- interface = dict(name=interface['name'])
- commands.extend(self._clear_config(interface, each))
- else:
- for each in have:
- want = dict()
- commands.extend(self._clear_config(want, each))
-
- return commands
-
- def _set_config(self, want, have):
- # Set the interface config based on the want and have config
- commands = []
- interface = 'interface ' + want['name']
-
- # Get the diff b/w want and have
- want_dict = dict_to_set(want)
- have_dict = dict_to_set(have)
- diff = want_dict - have_dict
-
- if diff:
- diff = dict(diff)
- for item in self.params:
- if diff.get(item):
- cmd = item + ' ' + str(want.get(item))
- add_command_to_config_list(interface, cmd, commands)
- if diff.get('enabled'):
- add_command_to_config_list(interface, 'no shutdown', commands)
- elif diff.get('enabled') is False:
- add_command_to_config_list(interface, 'shutdown', commands)
-
- return commands
-
- def _clear_config(self, want, have):
- # Delete the interface config based on the want and have config
- commands = []
-
- if want.get('name'):
- interface_type = get_interface_type(want['name'])
- interface = 'interface ' + want['name']
- else:
- interface_type = get_interface_type(have['name'])
- interface = 'interface ' + have['name']
-
- if have.get('description') and want.get('description') != have.get('description'):
- remove_command_from_config_list(interface, 'description', commands)
- if not have.get('enabled') and want.get('enabled') != have.get('enabled'):
- # if enable is False set enable as True which is the default behavior
- remove_command_from_config_list(interface, 'shutdown', commands)
-
- if interface_type.lower() == 'gigabitethernet':
- if have.get('speed') and have.get('speed') != 'auto' and want.get('speed') != have.get('speed'):
- remove_command_from_config_list(interface, 'speed', commands)
- if have.get('duplex') and have.get('duplex') != 'auto' and want.get('duplex') != have.get('duplex'):
- remove_command_from_config_list(interface, 'duplex', commands)
- if have.get('mtu') and want.get('mtu') != have.get('mtu'):
- remove_command_from_config_list(interface, 'mtu', commands)
-
- return commands
diff --git a/lib/ansible/module_utils/network/ios/config/l2_interfaces/l2_interfaces.py b/lib/ansible/module_utils/network/ios/config/l2_interfaces/l2_interfaces.py
deleted file mode 100644
index 1ebfcbda58..0000000000
--- a/lib/ansible/module_utils/network/ios/config/l2_interfaces/l2_interfaces.py
+++ /dev/null
@@ -1,336 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat Inc.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-The ios_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
-from ansible.module_utils.network.ios.facts.facts import Facts
-from ansible.module_utils.network.ios.utils.utils import dict_to_set
-from ansible.module_utils.network.ios.utils.utils import remove_command_from_config_list, add_command_to_config_list
-from ansible.module_utils.network.ios.utils.utils import filter_dict_having_none_value, remove_duplicate_interface
-
-
-class L2_Interfaces(ConfigBase):
- """
- The ios_l2_interfaces class
- """
-
- gather_subset = [
- '!all',
- '!min',
- ]
-
- gather_network_resources = [
- 'l2_interfaces',
- ]
-
- access_cmds = {'access_vlan': 'switchport access vlan'}
- voice_cmds = {'voice_vlan': 'switchport voice vlan'}
- trunk_cmds = {'encapsulation': 'switchport trunk encapsulation', 'pruning_vlans': 'switchport trunk pruning vlan',
- 'native_vlan': 'switchport trunk native vlan', 'allowed_vlans': 'switchport trunk allowed vlan'}
-
- 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('l2_interfaces')
- if not interfaces_facts:
- return []
-
- return interfaces_facts
-
- def execute_module(self):
- """ Execute the module
- :rtype: A dictionary
- :returns: The result from moduel execution
- """
- result = {'changed': False}
- commands = []
- warnings = []
- existing_facts = self.get_interfaces_facts()
- commands.extend(self.set_config(existing_facts))
- result['before'] = existing_facts
- if commands:
- if not self._module.check_mode:
- self._connection.edit_config(commands)
- result['changed'] = True
- result['commands'] = commands
-
- interfaces_facts = self.get_interfaces_facts()
-
- if result['changed']:
- result['after'] = interfaces_facts
- result['warnings'] = warnings
- return result
-
- def set_config(self, existing_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 deisred configuration
- """
-
- want = self._module.params['config']
- have = existing_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 deisred configuration
- """
- commands = []
-
- state = self._module.params['state']
- if state in ('overridden', 'merged', 'replaced') and not want:
- self._module.fail_json(msg='value of config parameter must not be empty for state {0}'.format(state))
-
- if state == 'overridden':
- commands = self._state_overridden(want, have, self._module)
- elif state == 'deleted':
- commands = self._state_deleted(want, have)
- elif state == 'merged':
- commands = self._state_merged(want, have, self._module)
- elif state == 'replaced':
- commands = self._state_replaced(want, have, self._module)
-
- return commands
-
- def _state_replaced(self, want, have, module):
- """ The command generator when state is replaced
- :param want: the desired configuration as a dictionary
- :param have: the current configuration as a dictionary
- :param interface_type: interface type
- :rtype: A list
- :returns: the commands necessary to migrate the current configuration
- to the deisred configuration
- """
- commands = []
-
- for interface in want:
- for each in have:
- if each['name'] == interface['name']:
- break
- else:
- continue
- have_dict = filter_dict_having_none_value(interface, each)
- commands.extend(self._clear_config(dict(), have_dict))
- commands.extend(self._set_config(interface, each, module))
- # Remove the duplicate interface call
- commands = remove_duplicate_interface(commands)
-
- return commands
-
- def _state_overridden(self, want, have, module):
- """ The command generator when state is overridden
- :param want: the desired configuration as a dictionary
- :param obj_in_have: the current configuration as a dictionary
- :rtype: A list
- :returns: the commands necessary to migrate the current configuration
- to the desired configuration
- """
- commands = []
-
- for each in have:
- for interface in want:
- if each['name'] == interface['name']:
- break
- else:
- # We didn't find a matching desired state, which means we can
- # pretend we received an empty desired state.
- interface = dict(name=each['name'])
- kwargs = {'want': interface, 'have': each}
- commands.extend(self._clear_config(**kwargs))
- continue
- have_dict = filter_dict_having_none_value(interface, each)
- commands.extend(self._clear_config(dict(), have_dict))
- commands.extend(self._set_config(interface, each, module))
- # Remove the duplicate interface call
- commands = remove_duplicate_interface(commands)
-
- return commands
-
- def _state_merged(self, want, have, module):
- """ The command generator when state is merged
- :param want: the additive configuration as a dictionary
- :param obj_in_have: the current configuration as a dictionary
- :rtype: A list
- :returns: the commands necessary to merge the provided into
- the current configuration
- """
- commands = []
-
- for interface in want:
- for each in have:
- if each['name'] == interface['name']:
- break
- else:
- continue
- commands.extend(self._set_config(interface, each, module))
-
- return commands
-
- def _state_deleted(self, want, have):
- """ The command generator when state is deleted
- :param want: the objects from which the configuration should be removed
- :param obj_in_have: the current configuration as a dictionary
- :param interface_type: interface type
- :rtype: A list
- :returns: the commands necessary to remove the current configuration
- of the provided objects
- """
- commands = []
-
- if want:
- for interface in want:
- for each in have:
- if each['name'] == interface['name']:
- break
- else:
- continue
- interface = dict(name=interface['name'])
- commands.extend(self._clear_config(interface, each))
- else:
- for each in have:
- want = dict()
- commands.extend(self._clear_config(want, each))
-
- return commands
-
- def _check_for_correct_vlan_range(self, vlan, module):
- # Function to check if the VLAN range passed is Valid
- for each in vlan:
- vlan_range = each.split('-')
- if len(vlan_range) > 1:
- if vlan_range[0] < vlan_range[1]:
- return True
- else:
- module.fail_json(msg='Command rejected: Bad VLAN list - end of range not larger than the'
- ' start of range!')
- else:
- return True
-
- def _set_config(self, want, have, module):
- # Set the interface config based on the want and have config
- commands = []
- interface = 'interface ' + want['name']
-
- # Get the diff b/w want and have
- want_dict = dict_to_set(want)
- have_dict = dict_to_set(have)
- want_trunk = dict(want_dict).get('trunk')
- have_trunk = dict(have_dict).get('trunk')
- if want_trunk and have_trunk:
- diff = set(tuple(dict(want_dict).get('trunk'))) - set(tuple(dict(have_dict).get('trunk')))
- else:
- diff = want_dict - have_dict
-
- if diff:
- diff = dict(diff)
- mode = diff.get('mode')
- access = diff.get('access')
- trunk = diff.get('trunk')
-
- if access:
- cmd = 'switchport access vlan {0}'.format(access[0][1])
- add_command_to_config_list(interface, cmd, commands)
-
- if diff.get('voice'):
- cmd = 'switchport voice vlan {0}'.format(diff.get('voice')[0][1])
- add_command_to_config_list(interface, cmd, commands)
-
- if want_trunk:
- if trunk:
- diff = dict(trunk)
- if diff.get('encapsulation'):
- cmd = self.trunk_cmds['encapsulation'] + ' {0}'.format(diff.get('encapsulation'))
- add_command_to_config_list(interface, cmd, commands)
- if diff.get('native_vlan'):
- cmd = self.trunk_cmds['native_vlan'] + ' {0}'.format(diff.get('native_vlan'))
- add_command_to_config_list(interface, cmd, commands)
- allowed_vlans = diff.get('allowed_vlans')
- pruning_vlans = diff.get('pruning_vlans')
-
- if allowed_vlans and self._check_for_correct_vlan_range(allowed_vlans, module):
- allowed_vlans = ','.join(allowed_vlans)
- cmd = self.trunk_cmds['allowed_vlans'] + ' {0}'.format(allowed_vlans)
- add_command_to_config_list(interface, cmd, commands)
- if pruning_vlans and self._check_for_correct_vlan_range(pruning_vlans, module):
- pruning_vlans = ','.join(pruning_vlans)
- cmd = self.trunk_cmds['pruning_vlans'] + ' {0}'.format(pruning_vlans)
- add_command_to_config_list(interface, cmd, commands)
-
- if mode:
- cmd = 'switchport mode {0}'.format(mode)
- add_command_to_config_list(interface, cmd, commands)
-
- return commands
-
- def _clear_config(self, want, have):
- # Delete the interface config based on the want and have config
- commands = []
- if want.get('name'):
- interface = 'interface ' + want['name']
- else:
- interface = 'interface ' + have['name']
-
- if have.get('mode') or want.get('mode'):
- remove_command_from_config_list(interface, 'switchport mode', commands)
-
- if have.get('access') and want.get('access') is None:
- remove_command_from_config_list(interface, L2_Interfaces.access_cmds['access_vlan'], commands)
- elif have.get('access') and want.get('access'):
- if have.get('access').get('vlan') != want.get('access').get('vlan'):
- remove_command_from_config_list(interface, L2_Interfaces.access_cmds['access_vlan'], commands)
-
- if have.get('voice') and want.get('voice') is None:
- remove_command_from_config_list(interface, L2_Interfaces.voice_cmds['voice_vlan'], commands)
- elif have.get('voice') and want.get('voice'):
- if have.get('voice').get('vlan') != want.get('voice').get('vlan'):
- remove_command_from_config_list(interface, L2_Interfaces.voice_cmds['voice_vlan'], commands)
-
- if have.get('trunk') and want.get('trunk') is None:
- # Check when no config is passed
- if have.get('trunk').get('encapsulation'):
- remove_command_from_config_list(interface, self.trunk_cmds['encapsulation'], commands)
- if have.get('trunk').get('native_vlan'):
- remove_command_from_config_list(interface, self.trunk_cmds['native_vlan'], commands)
- if have.get('trunk').get('allowed_vlans'):
- remove_command_from_config_list(interface, self.trunk_cmds['allowed_vlans'], commands)
- if have.get('trunk').get('pruning_vlans'):
- remove_command_from_config_list(interface, self.trunk_cmds['pruning_vlans'], commands)
- elif have.get('trunk') and want.get('trunk'):
- # Check when config is passed, also used in replaced and override state
- if have.get('trunk').get('encapsulation')\
- and have.get('trunk').get('encapsulation') != want.get('trunk').get('encapsulation'):
- remove_command_from_config_list(interface, self.trunk_cmds['encapsulation'], commands)
- if have.get('trunk').get('native_vlan') \
- and have.get('trunk').get('native_vlan') != want.get('trunk').get('native_vlan'):
- remove_command_from_config_list(interface, self.trunk_cmds['native_vlan'], commands)
- if have.get('trunk').get('allowed_vlans') \
- and have.get('trunk').get('allowed_vlans') != want.get('trunk').get('allowed_vlans'):
- remove_command_from_config_list(interface, self.trunk_cmds['allowed_vlans'], commands)
- if have.get('trunk').get('pruning_vlans') \
- and have.get('trunk').get('pruning_vlans') != want.get('trunk').get('pruning_vlans'):
- remove_command_from_config_list(interface, self.trunk_cmds['pruning_vlans'], commands)
-
- return commands
diff --git a/lib/ansible/module_utils/network/ios/config/l3_interfaces/l3_interfaces.py b/lib/ansible/module_utils/network/ios/config/l3_interfaces/l3_interfaces.py
deleted file mode 100644
index 221f276ab2..0000000000
--- a/lib/ansible/module_utils/network/ios/config/l3_interfaces/l3_interfaces.py
+++ /dev/null
@@ -1,328 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat Inc.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-The ios_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
-from ansible.module_utils.network.ios.facts.facts import Facts
-from ansible.module_utils.network.ios.utils.utils import dict_to_set
-from ansible.module_utils.network.ios.utils.utils import remove_command_from_config_list, add_command_to_config_list
-from ansible.module_utils.network.ios.utils.utils import filter_dict_having_none_value, remove_duplicate_interface
-from ansible.module_utils.network.ios.utils.utils import validate_n_expand_ipv4, validate_ipv6
-
-
-class L3_Interfaces(ConfigBase):
- """
- The ios_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
- """
- commands = []
-
- state = self._module.params['state']
- if state in ('overridden', 'merged', 'replaced') and not want:
- self._module.fail_json(msg='value of config parameter must not be empty for state {0}'.format(state))
-
- if state == 'overridden':
- commands = self._state_overridden(want, have, self._module)
- elif state == 'deleted':
- commands = self._state_deleted(want, have)
- elif state == 'merged':
- commands = self._state_merged(want, have, self._module)
- elif state == 'replaced':
- commands = self._state_replaced(want, have, self._module)
-
- return commands
-
- def _state_replaced(self, want, have, module):
- """ The command generator when state is replaced
- :rtype: A list
- :returns: the commands necessary to migrate the current configuration
- to the desired configuration
- """
- commands = []
-
- for interface in want:
- for each in have:
- if each['name'] == interface['name']:
- break
- else:
- if '.' in interface['name']:
- commands.extend(self._set_config(interface, dict(), module))
- continue
- have_dict = filter_dict_having_none_value(interface, each)
- commands.extend(self._clear_config(dict(), have_dict))
- commands.extend(self._set_config(interface, each, module))
- # Remove the duplicate interface call
- commands = remove_duplicate_interface(commands)
-
- return commands
-
- def _state_overridden(self, want, have, module):
- """ The command generator when state is overridden
- :rtype: A list
- :returns: the commands necessary to migrate the current configuration
- to the desired configuration
- """
- commands = []
-
- for each in have:
- for interface in want:
- if each['name'] == interface['name']:
- break
- else:
- # We didn't find a matching desired state, which means we can
- # pretend we received an empty desired state.
- interface = dict(name=each['name'])
- kwargs = {'want': interface, 'have': each}
- commands.extend(self._clear_config(**kwargs))
- continue
- have_dict = filter_dict_having_none_value(interface, each)
- commands.extend(self._clear_config(dict(), have_dict))
- commands.extend(self._set_config(interface, each, module))
- # Remove the duplicate interface call
- commands = remove_duplicate_interface(commands)
-
- return commands
-
- def _state_merged(self, want, have, module):
- """ The command generator when state is merged
- :rtype: A list
- :returns: the commands necessary to merge the provided into
- the current configuration
- """
- commands = []
-
- for interface in want:
- for each in have:
- if each['name'] == interface['name']:
- break
- else:
- if '.' in interface['name']:
- commands.extend(self._set_config(interface, dict(), module))
- continue
- commands.extend(self._set_config(interface, each, module))
-
- return commands
-
- def _state_deleted(self, want, have):
- """ The command generator when state is deleted
- :rtype: A list
- :returns: the commands necessary to remove the current configuration
- of the provided objects
- """
- commands = []
-
- if want:
- for interface in want:
- for each in have:
- if each['name'] == interface['name']:
- break
- elif interface['name'] in each['name']:
- break
- else:
- continue
- interface = dict(name=interface['name'])
- commands.extend(self._clear_config(interface, each))
- else:
- for each in have:
- want = dict()
- commands.extend(self._clear_config(want, each))
-
- return commands
-
- def verify_diff_again(self, want, have):
- """
- Verify the IPV4 difference again as sometimes due to
- change in order of set, set difference may result into change,
- when there's actually no difference between want and have
- :param want: want_dict IPV4
- :param have: have_dict IPV4
- :return: diff
- """
- diff = False
- for each in want:
- each_want = dict(each)
- for every in have:
- every_have = dict(every)
- if each_want.get('address') != every_have.get('address') and \
- each_want.get('secondary') != every_have.get('secondary') and \
- len(each_want.keys()) == len(every_have.keys()):
- diff = True
- break
- elif each_want.get('dhcp_client') != every_have.get('dhcp_client') and each_want.get(
- 'dhcp_client') is not None:
- diff = True
- break
- elif each_want.get('dhcp_hostname') != every_have.get('dhcp_hostname') and each_want.get(
- 'dhcp_hostname') is not None:
- diff = True
- break
- elif each_want.get('address') != every_have.get('address') and len(each_want.keys()) == len(
- every_have.keys()):
- diff = True
- break
- if diff:
- break
-
- return diff
-
- def _set_config(self, want, have, module):
- # Set the interface config based on the want and have config
- commands = []
- interface = 'interface ' + want['name']
-
- # To handle L3 IPV4 configuration
- if want.get("ipv4"):
- for each in want.get("ipv4"):
- if each.get('address') != 'dhcp':
- ip_addr_want = validate_n_expand_ipv4(module, each)
- each['address'] = ip_addr_want
-
- # Convert the want and have dict to set
- want_dict = dict_to_set(want)
- have_dict = dict_to_set(have)
-
- # To handle L3 IPV4 configuration
- if want.get('ipv4'):
- # Get the diff b/w want and have IPV4
- if have.get('ipv4'):
- ipv4 = tuple(set(dict(want_dict).get('ipv4')) - set(dict(have_dict).get('ipv4')))
- if ipv4:
- ipv4 = ipv4 if self.verify_diff_again(dict(want_dict).get('ipv4'), dict(have_dict).get('ipv4')) else ()
- else:
- diff = want_dict - have_dict
- ipv4 = dict(diff).get('ipv4')
- if ipv4:
- for each in ipv4:
- ipv4_dict = dict(each)
- if ipv4_dict.get('address') != 'dhcp':
- cmd = "ip address {0}".format(ipv4_dict['address'])
- if ipv4_dict.get("secondary"):
- cmd += " secondary"
- elif ipv4_dict.get('address') == 'dhcp':
- cmd = "ip address dhcp"
- if ipv4_dict.get('dhcp_client') is not None and ipv4_dict.get('dhcp_hostname'):
- cmd = "ip address dhcp client-id GigabitEthernet 0/{0} hostname {1}"\
- .format(ipv4_dict.get('dhcp_client'), ipv4_dict.get('dhcp_hostname'))
- elif ipv4_dict.get('dhcp_client') and not ipv4_dict.get('dhcp_hostname'):
- cmd = "ip address dhcp client-id GigabitEthernet 0/{0}"\
- .format(ipv4_dict.get('dhcp_client'))
- elif not ipv4_dict.get('dhcp_client') and ipv4_dict.get('dhcp_hostname'):
- cmd = "ip address dhcp hostname {0}".format(ipv4_dict.get('dhcp_client'))
-
- add_command_to_config_list(interface, cmd, commands)
-
- # To handle L3 IPV6 configuration
- if want.get('ipv6'):
- # Get the diff b/w want and have IPV6
- if have.get('ipv6'):
- ipv6 = tuple(set(dict(want_dict).get('ipv6')) - set(dict(have_dict).get('ipv6')))
- else:
- diff = want_dict - have_dict
- ipv6 = dict(diff).get('ipv6')
- if ipv6:
- for each in ipv6:
- ipv6_dict = dict(each)
- validate_ipv6(ipv6_dict.get('address'), module)
- cmd = "ipv6 address {0}".format(ipv6_dict.get('address'))
- add_command_to_config_list(interface, cmd, commands)
-
- return commands
-
- def _clear_config(self, want, have):
- # Delete the interface config based on the want and have config
- count = 0
- commands = []
- if want.get('name'):
- interface = 'interface ' + want['name']
- else:
- interface = 'interface ' + have['name']
-
- if have.get('ipv4') and want.get('ipv4'):
- for each in have.get('ipv4'):
- if each.get('secondary') and not (want.get('ipv4')[count].get('secondary')):
- cmd = 'ipv4 address {0} secondary'.format(each.get('address'))
- remove_command_from_config_list(interface, cmd, commands)
- count += 1
- if have.get('ipv4') and not want.get('ipv4'):
- remove_command_from_config_list(interface, 'ip address', commands)
- if have.get('ipv6') and not want.get('ipv6'):
- remove_command_from_config_list(interface, 'ipv6 address', commands)
- return commands
diff --git a/lib/ansible/module_utils/network/ios/config/lacp/lacp.py b/lib/ansible/module_utils/network/ios/config/lacp/lacp.py
deleted file mode 100644
index 3f6bc0c0eb..0000000000
--- a/lib/ansible/module_utils/network/ios/config/lacp/lacp.py
+++ /dev/null
@@ -1,189 +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 ios_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
-from ansible.module_utils.network.ios.facts.facts import Facts
-from ansible.module_utils.network.ios.utils.utils import dict_to_set
-
-
-class Lacp(ConfigBase):
- """
- The ios_lacp class
- """
-
- gather_subset = [
- '!all',
- '!min',
- ]
-
- gather_network_resources = [
- 'lacp',
- ]
-
- def __init__(self, module):
- super(Lacp, self).__init__(module)
-
- 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}
- commands = list()
- warnings = 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']
- 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 in ('merged', 'replaced') and not want:
- self._module.fail_json(msg='value of config parameter must not be empty for state {0}'.format(state))
-
- if state == 'deleted':
- commands = self._state_deleted(want, have)
- elif state == 'merged':
- commands = self._state_merged(want, have)
- elif state == 'replaced':
- commands = self._state_replaced(want, have)
-
- return commands
-
- def _state_replaced(self, want, have):
- """ The command generator when state is replaced
-
- :rtype: A list
- :returns: the commands necessary to migrate the current configuration
- to the desired configuration
- """
- commands = []
-
- commands.extend(self._set_config(want, have))
-
- return commands
-
- def _state_merged(self, want, have):
- """ The command generator when state is merged
-
- :rtype: A list
- :returns: the commands necessary to merge the provided into
- the current configuration
- """
- commands = []
-
- commands.extend(self._set_config(want, have))
-
- return commands
-
- def _state_deleted(self, want, have):
- """ The command generator when state is deleted
-
- :rtype: A list
- :returns: the commands necessary to remove the current configuration
- of the provided objects
- """
- commands = []
-
- if want:
- commands.extend(self._clear_config(have))
- else:
- commands.extend(self._clear_config(have))
-
- return commands
-
- def _remove_command_from_config_list(self, cmd, commands):
- commands.append('no %s' % cmd)
- return commands
-
- def _add_command_to_config_list(self, cmd, commands):
- if cmd not in commands:
- commands.append(cmd)
-
- def _set_config(self, want, have):
- # Set the interface config based on the want and have config
- commands = []
-
- want_dict = dict_to_set(want)
- have_dict = dict_to_set(have)
- diff = want_dict - have_dict
-
- if diff:
- cmd = 'lacp system-priority {0}'.format(want.get('system').get('priority'))
- self._add_command_to_config_list(cmd, commands)
-
- return commands
-
- def _clear_config(self, have):
- # Delete the interface config based on the want and have config
- commands = []
-
- if have.get('system').get('priority') and have.get('system').get('priority') != 32768:
- cmd = 'lacp system-priority'
- self._remove_command_from_config_list(cmd, commands)
-
- return commands
diff --git a/lib/ansible/module_utils/network/ios/config/lacp_interfaces/lacp_interfaces.py b/lib/ansible/module_utils/network/ios/config/lacp_interfaces/lacp_interfaces.py
deleted file mode 100644
index 71ac96d0c3..0000000000
--- a/lib/ansible/module_utils/network/ios/config/lacp_interfaces/lacp_interfaces.py
+++ /dev/null
@@ -1,260 +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 ios_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
-from ansible.module_utils.network.ios.facts.facts import Facts
-from ansible.module_utils.network.ios.utils.utils import dict_to_set
-from ansible.module_utils.network.ios.utils.utils import remove_command_from_config_list, add_command_to_config_list
-from ansible.module_utils.network.ios.utils.utils import filter_dict_having_none_value, remove_duplicate_interface
-
-
-class Lacp_Interfaces(ConfigBase):
- """
- The ios_lacp_interfaces class
- """
-
- gather_subset = [
- '!all',
- '!min',
- ]
-
- gather_network_resources = [
- 'lacp_interfaces',
- ]
-
- def __init__(self, module):
- super(Lacp_Interfaces, self).__init__(module)
-
- def get_lacp_interfaces_facts(self):
- """ 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}
- commands = list()
- warnings = 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
- """
- commands = []
-
- state = self._module.params['state']
- if state in ('overridden', 'merged', 'replaced') and not want:
- self._module.fail_json(msg='value of config parameter must not be empty for state {0}'.format(state))
-
- if state == 'overridden':
- commands = 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
-
- def _state_replaced(self, want, have):
- """ The command generator when state is replaced
-
- :rtype: A list
- :returns: the commands necessary to migrate the current configuration
- to the desired configuration
- """
- commands = []
-
- for interface in want:
- for each in have:
- if each['name'] == interface['name']:
- break
- else:
- continue
- have_dict = filter_dict_having_none_value(interface, each)
- commands.extend(self._clear_config(dict(), have_dict))
- commands.extend(self._set_config(interface, each))
- # Remove the duplicate interface call
- commands = remove_duplicate_interface(commands)
-
- return commands
-
- def _state_overridden(self, want, have):
- """ The command generator when state is overridden
-
- :rtype: A list
- :returns: the commands necessary to migrate the current configuration
- to the desired configuration
- """
- commands = []
-
- for each in have:
- for interface in want:
- if each['name'] == interface['name']:
- break
- else:
- # We didn't find a matching desired state, which means we can
- # pretend we received an empty desired state.
- interface = dict(name=each['name'])
- commands.extend(self._clear_config(interface, each))
- continue
- have_dict = filter_dict_having_none_value(interface, each)
- commands.extend(self._clear_config(dict(), have_dict))
- commands.extend(self._set_config(interface, each))
- # Remove the duplicate interface call
- commands = remove_duplicate_interface(commands)
-
- return commands
-
- def _state_merged(self, want, have):
- """ The command generator when state is merged
-
- :rtype: A list
- :returns: the commands necessary to merge the provided into
- the current configuration
- """
- commands = []
-
- for interface in want:
- for each in have:
- if interface['name'] == each['name']:
- break
- else:
- continue
- commands.extend(self._set_config(interface, each))
-
- return commands
-
- def _state_deleted(self, want, have):
- """ The command generator when state is deleted
-
- :rtype: A list
- :returns: the commands necessary to remove the current configuration
- of the provided objects
- """
- commands = []
-
- if want:
- for interface in want:
- for each in have:
- if each['name'] == interface['name']:
- break
- else:
- continue
- interface = dict(name=interface['name'])
- commands.extend(self._clear_config(interface, each))
- else:
- for each in have:
- commands.extend(self._clear_config(dict(), each))
-
- return commands
-
- def _set_config(self, want, have):
- # Set the interface config based on the want and have config
- commands = []
- interface = 'interface ' + have['name']
-
- want_dict = dict_to_set(want)
- have_dict = dict_to_set(have)
- diff = want_dict - have_dict
-
- if diff:
- port_priotity = dict(diff).get('port_priority')
- max_bundle = dict(diff).get('max_bundle')
- fast_switchover = dict(diff).get('fast_switchover')
- if port_priotity:
- cmd = 'lacp port-priority {0}'.format(port_priotity)
- add_command_to_config_list(interface, cmd, commands)
- if max_bundle:
- cmd = 'lacp max-bundle {0}'.format(max_bundle)
- add_command_to_config_list(interface, cmd, commands)
- if fast_switchover:
- cmd = 'lacp fast-switchover'
- add_command_to_config_list(interface, cmd, commands)
-
- return commands
-
- def _clear_config(self, want, have):
- # Delete the interface config based on the want and have config
- commands = []
- if want.get('name'):
- interface = 'interface ' + want['name']
- else:
- interface = 'interface ' + have['name']
-
- if have.get('port_priority') and have.get('port_priority') != want.get('port_priority'):
- cmd = 'lacp port-priority'
- remove_command_from_config_list(interface, cmd, commands)
- if have.get('max_bundle') and have.get('max_bundle') != want.get('max_bundle'):
- cmd = 'lacp max-bundle'
- remove_command_from_config_list(interface, cmd, commands)
- if have.get('fast_switchover'):
- cmd = 'lacp fast-switchover'
- remove_command_from_config_list(interface, cmd, commands)
-
- return commands
diff --git a/lib/ansible/module_utils/network/ios/config/lag_interfaces/lag_interfaces.py b/lib/ansible/module_utils/network/ios/config/lag_interfaces/lag_interfaces.py
deleted file mode 100644
index c4760c1061..0000000000
--- a/lib/ansible/module_utils/network/ios/config/lag_interfaces/lag_interfaces.py
+++ /dev/null
@@ -1,296 +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 ios_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
-
-
-import re
-from ansible.module_utils.network.common import utils
-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.ios.facts.facts import Facts
-from ansible.module_utils.network.ios.utils.utils import dict_to_set
-from ansible.module_utils.network.ios.utils.utils import filter_dict_having_none_value, remove_duplicate_interface
-
-
-class Lag_interfaces(ConfigBase):
- """
- The ios_lag_interfaces class
- """
-
- gather_subset = [
- '!all',
- '!min',
- ]
-
- gather_network_resources = [
- 'lag_interfaces',
- ]
-
- def __init__(self, module):
- super(Lag_interfaces, self).__init__(module)
-
- def get_lag_interfaces_facts(self):
- """ 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 in ('overridden', 'merged', 'replaced') and not want:
- self._module.fail_json(msg='value of config parameter must not be empty for state {0}'.format(state))
-
- module = self._module
- if state == 'overridden':
- commands = self._state_overridden(want, have, module)
- elif state == 'deleted':
- commands = self._state_deleted(want, have)
- elif state == 'merged':
- commands = self._state_merged(want, have, module)
- elif state == 'replaced':
- commands = self._state_replaced(want, have, module)
- return commands
-
- def _state_replaced(self, want, have, module):
- """ The command generator when state is replaced
-
- :rtype: A list
- :returns: the commands necessary to migrate the current configuration
- to the desired configuration
- """
- commands = []
-
- for interface in want:
- for each_interface in interface.get('members'):
- for each in have:
- if each.get('members'):
- for every in each.get('members'):
- match = False
- if every['member'] == each_interface['member']:
- match = True
- break
- else:
- continue
- if match:
- have_dict = filter_dict_having_none_value(interface, each)
- commands.extend(self._clear_config(dict(), have_dict))
- commands.extend(self._set_config(interface, each, module))
- elif each.get('name') == each_interface['member']:
- have_dict = filter_dict_having_none_value(interface, each)
- commands.extend(self._clear_config(dict(), have_dict))
- commands.extend(self._set_config(interface, each, module))
- break
- # Remove the duplicate interface call
- commands = remove_duplicate_interface(commands)
-
- return commands
-
- def _state_overridden(self, want, have, module):
- """ The command generator when state is overridden
-
- :rtype: A list
- :returns: the commands necessary to migrate the current configuration
- to the desired configuration
- """
- commands = []
-
- for interface in want:
- for each_interface in interface.get('members'):
- for each in have:
- if each.get('members'):
- for every in each.get('members'):
- match = False
- if every['member'] == each_interface['member']:
- match = True
- break
- else:
- commands.extend(self._clear_config(interface, each))
- continue
- if match:
- have_dict = filter_dict_having_none_value(interface, each)
- commands.extend(self._clear_config(dict(), have_dict))
- commands.extend(self._set_config(interface, each, module))
- elif each.get('name') == each_interface['member']:
- have_dict = filter_dict_having_none_value(interface, each)
- commands.extend(self._clear_config(dict(), have_dict))
- commands.extend(self._set_config(interface, each, module))
- break
- # Remove the duplicate interface call
- commands = remove_duplicate_interface(commands)
-
- return commands
-
- def _state_merged(self, want, have, module):
- """ The command generator when state is merged
-
- :rtype: A list
- :returns: the commands necessary to merge the provided into
- the current configuration
- """
- commands = []
-
- for interface in want:
- for each_interface in interface.get('members'):
- for each in have:
- if each.get('members'):
- for every in each.get('members'):
- if every['member'] == each_interface['member']:
- break
- elif each.get('name') == each_interface['member']:
- break
- else:
- continue
- commands.extend(self._set_config(interface, each, module))
-
- return commands
-
- def _state_deleted(self, want, have):
- """ The command generator when state is deleted
-
- :rtype: A list
- :returns: the commands necessary to remove the current configuration
- of the provided objects
- """
- commands = []
-
- if want:
- for interface in want:
- for each in have:
- if each.get('name') == interface['name']:
- break
- else:
- continue
- commands.extend(self._clear_config(interface, each))
- else:
- for each in have:
- commands.extend(self._clear_config(dict(), each))
-
- return commands
-
- def remove_command_from_config_list(self, interface, cmd, commands):
- # To delete the passed config
- if interface not in commands:
- commands.append(interface)
- commands.append('no %s' % cmd)
- return commands
-
- def add_command_to_config_list(self, interface, cmd, commands):
- # To set the passed config
- if interface not in commands:
- commands.append(interface)
- commands.append(cmd)
- return commands
-
- def _set_config(self, want, have, module):
- # Set the interface config based on the want and have config
- commands = []
-
- # To remove keys with None values from want dict
- want = utils.remove_empties(want)
- # Get the diff b/w want and have
- want_dict = dict_to_set(want)
- have_dict = dict_to_set(have)
- diff = want_dict - have_dict
-
- # To get the channel-id from lag port-channel name
- lag_config = dict(diff).get('members')
- channel_name = re.search(r'(\d+)', want.get('name'))
- if channel_name:
- channel_id = channel_name.group()
- else:
- module.fail_json(msg="Lag Interface Name is not correct!")
- if lag_config:
- for each in lag_config:
- each = dict(each)
- each_interface = 'interface {0}'.format(each.get('member'))
- if have.get('name') == want['members'][0]['member'] or have.get('name').lower().startswith('po'):
- if each.get('mode'):
- cmd = 'channel-group {0} mode {1}'.format(channel_id, each.get('mode'))
- self.add_command_to_config_list(each_interface, cmd, commands)
- elif each.get('link'):
- cmd = 'channel-group {0} link {1}'.format(channel_id, each.get('link'))
- self.add_command_to_config_list(each_interface, cmd, commands)
-
- return commands
-
- def _clear_config(self, want, have):
- # Delete the interface config based on the want and have config
- commands = []
-
- if have.get('members'):
- for each in have['members']:
- interface = 'interface ' + each['member']
- if want.get('members'):
- if each.get('member') and each.get('member') != want['members'][0]['member']:
- self.remove_command_from_config_list(interface, 'channel-group', commands)
- elif each.get('member'):
- self.remove_command_from_config_list(interface, 'channel-group', commands)
-
- return commands
diff --git a/lib/ansible/module_utils/network/ios/config/lldp_global/lldp_global.py b/lib/ansible/module_utils/network/ios/config/lldp_global/lldp_global.py
deleted file mode 100644
index a3f6dd6091..0000000000
--- a/lib/ansible/module_utils/network/ios/config/lldp_global/lldp_global.py
+++ /dev/null
@@ -1,238 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat Inc.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-The ios_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 its desired end-state is
-created
-"""
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-from ansible.module_utils.six import iteritems
-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.ios.facts.facts import Facts
-from ansible.module_utils.network.ios.utils.utils import dict_to_set
-from ansible.module_utils.network.ios.utils.utils import filter_dict_having_none_value
-
-
-class Lldp_global(ConfigBase):
- """
- The ios_lldp_global class
- """
-
- gather_subset = [
- '!all',
- '!min',
- ]
-
- gather_network_resources = [
- 'lldp_global',
- ]
-
- tlv_select_params = {'four_wire_power_management': '4-wire-power-management', 'mac_phy_cfg': 'mac-phy-cfg',
- 'management_address': 'management-address', 'port_description': 'port-description',
- 'port_vlan': 'port-vlan', 'power_management': 'power-management',
- 'system_capabilities': 'system-capabilities', 'system_description': 'system-description',
- 'system_name': 'system-name'}
-
- 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 moduel execution
- """
- result = {'changed': False}
- commands = list()
- warnings = 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 deisred configuration
- """
- want = self._module.params['config']
- 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 deisred configuration
- """
- commands = []
- state = self._module.params['state']
- if state in ('merged', 'replaced') and not want:
- self._module.fail_json(msg='value of config parameter must not be empty for state {0}'.format(state))
-
- if state == 'overridden':
- commands = 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
-
- def _state_replaced(self, want, have):
- """ The command generator when state is replaced
-
- :param want: the desired configuration as a dictionary
- :param have: the current configuration as a dictionary
- :param interface_type: interface type
- :rtype: A list
- :returns: the commands necessary to migrate the current configuration
- to the deisred configuration
- """
- commands = []
-
- have_dict = filter_dict_having_none_value(want, have)
- commands.extend(self._clear_config(have_dict))
- commands.extend(self._set_config(want, have))
-
- return commands
-
- def _state_merged(self, want, have):
- """ The command generator when state is merged
-
- :param want: the additive configuration as a dictionary
- :param obj_in_have: the current configuration as a dictionary
- :rtype: A list
- :returns: the commands necessary to merge the provided into
- the current configuration
- """
- commands = []
-
- commands.extend(self._set_config(want, have))
-
- return commands
-
- def _state_deleted(self, want, have):
- """ The command generator when state is deleted
-
- :param want: the objects from which the configuration should be removed
- :param obj_in_have: the current configuration as a dictionary
- :param interface_type: interface type
- :rtype: A list
- :returns: the commands necessary to remove the current configuration
- of the provided objects
- """
- commands = []
-
- commands.extend(self._clear_config(have))
-
- return commands
-
- def _remove_command_from_config_list(self, cmd, commands):
- if cmd not in commands:
- commands.append('no %s' % cmd)
-
- def add_command_to_config_list(self, cmd, commands):
- if cmd not in commands:
- commands.append(cmd)
-
- def _set_config(self, want, have):
- # Set the interface config based on the want and have config
- commands = []
-
- # Get the diff b/w want and have
- want_dict = dict_to_set(want)
- have_dict = dict_to_set(have)
- diff = want_dict - have_dict
-
- if diff:
- diff = dict(diff)
- holdtime = diff.get('holdtime')
- enabled = diff.get('enabled')
- timer = diff.get('timer')
- reinit = diff.get('reinit')
- tlv_select = diff.get('tlv_select')
-
- if holdtime:
- cmd = 'lldp holdtime {0}'.format(holdtime)
- self.add_command_to_config_list(cmd, commands)
- if enabled:
- cmd = 'lldp run'
- self.add_command_to_config_list(cmd, commands)
- if timer:
- cmd = 'lldp timer {0}'.format(timer)
- self.add_command_to_config_list(cmd, commands)
- if reinit:
- cmd = 'lldp reinit {0}'.format(reinit)
- self.add_command_to_config_list(cmd, commands)
- if tlv_select:
- tlv_selec_dict = dict(tlv_select)
- for k, v in iteritems(self.tlv_select_params):
- if k in tlv_selec_dict and tlv_selec_dict[k]:
- cmd = 'lldp tlv-select {0}'.format(v)
- self.add_command_to_config_list(cmd, commands)
-
- return commands
-
- def _clear_config(self, have):
- # Delete the interface config based on the want and have config
- commands = []
-
- if have.get('holdtime'):
- cmd = 'lldp holdtime'
- self._remove_command_from_config_list(cmd, commands)
- if have.get('enabled'):
- cmd = 'lldp run'
- self._remove_command_from_config_list(cmd, commands)
- if have.get('timer'):
- cmd = 'lldp timer'
- self._remove_command_from_config_list(cmd, commands)
- if have.get('reinit'):
- cmd = 'lldp reinit'
- self._remove_command_from_config_list(cmd, commands)
-
- return commands
diff --git a/lib/ansible/module_utils/network/ios/config/lldp_interfaces/lldp_interfaces.py b/lib/ansible/module_utils/network/ios/config/lldp_interfaces/lldp_interfaces.py
deleted file mode 100644
index 57a6a3cd4c..0000000000
--- a/lib/ansible/module_utils/network/ios/config/lldp_interfaces/lldp_interfaces.py
+++ /dev/null
@@ -1,270 +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 ios_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 its 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
-from ansible.module_utils.network.ios.facts.facts import Facts
-from ansible.module_utils.network.ios.utils.utils import dict_to_set
-from ansible.module_utils.network.ios.utils.utils import remove_command_from_config_list, add_command_to_config_list
-from ansible.module_utils.network.ios.utils.utils import filter_dict_having_none_value, remove_duplicate_interface
-
-
-class Lldp_Interfaces(ConfigBase):
- """
- The ios_lldp_interfaces class
- """
-
- gather_subset = [
- '!all',
- '!min',
- ]
-
- gather_network_resources = [
- 'lldp_interfaces',
- ]
-
- def __init__(self, module):
- super(Lldp_Interfaces, self).__init__(module)
-
- def get_lldp_interfaces_facts(self):
- """ 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}
- commands = list()
- warnings = 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']
- if state in ('overridden', 'merged', 'replaced') and not want:
- self._module.fail_json(msg='value of config parameter must not be empty for state {0}'.format(state))
-
- if state == 'overridden':
- commands = 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
-
- def _state_replaced(self, want, have):
- """ The command generator when state is replaced
-
- :rtype: A list
- :returns: the commands necessary to migrate the current configuration
- to the desired configuration
- """
- commands = []
-
- for interface in want:
- for each in have:
- if each['name'] == interface['name']:
- break
- else:
- continue
- have_dict = filter_dict_having_none_value(interface, each)
- commands.extend(self._clear_config(dict(), have_dict))
- commands.extend(self._set_config(interface, each))
- # Remove the duplicate interface call
- commands = remove_duplicate_interface(commands)
-
- return commands
-
- def _state_overridden(self, want, have):
- """ The command generator when state is overridden
-
- :rtype: A list
- :returns: the commands necessary to migrate the current configuration
- to the desired configuration
- """
- commands = []
-
- for each in have:
- for interface in want:
- if each['name'] == interface['name']:
- break
- else:
- # We didn't find a matching desired state, which means we can
- # pretend we received an empty desired state.
- interface = dict(name=each['name'])
- commands.extend(self._clear_config(interface, each))
- continue
- have_dict = filter_dict_having_none_value(interface, each)
- commands.extend(self._clear_config(dict(), have_dict))
- commands.extend(self._set_config(interface, each))
- # Remove the duplicate interface call
- commands = remove_duplicate_interface(commands)
-
- return commands
-
- def _state_merged(self, want, have):
- """ The command generator when state is merged
-
- :rtype: A list
- :returns: the commands necessary to merge the provided into
- the current configuration
- """
- commands = []
-
- for interface in want:
- for each in have:
- if interface['name'] == each['name']:
- break
- else:
- continue
- commands.extend(self._set_config(interface, each))
-
- return commands
-
- def _state_deleted(self, want, have):
- """ The command generator when state is deleted
-
- :rtype: A list
- :returns: the commands necessary to remove the current configuration
- of the provided objects
- """
- commands = []
-
- if want:
- for interface in want:
- for each in have:
- if each['name'] == interface['name']:
- break
- else:
- continue
- interface = dict(name=interface['name'])
- commands.extend(self._clear_config(interface, each))
- else:
- for each in have:
- commands.extend(self._clear_config(dict(), each))
-
- return commands
-
- def _set_config(self, want, have):
- # Set the interface config based on the want and have config
- commands = []
-
- interface = 'interface ' + have['name']
- # Get the diff b/w want and have
- want_dict = dict_to_set(want)
- have_dict = dict_to_set(have)
- diff = want_dict - have_dict
-
- if diff:
- diff = dict(diff)
- receive = diff.get('receive')
- transmit = diff.get('transmit')
- med_tlv_select = diff.get('med_tlv_select')
- tlv_select = diff.get('tlv_select')
- if receive:
- cmd = 'lldp receive'
- add_command_to_config_list(interface, cmd, commands)
- elif receive is False:
- cmd = 'no lldp receive'
- add_command_to_config_list(interface, cmd, commands)
- if transmit:
- cmd = 'lldp transmit'
- add_command_to_config_list(interface, cmd, commands)
- elif transmit is False:
- cmd = 'no lldp transmit'
- add_command_to_config_list(interface, cmd, commands)
-
- if med_tlv_select:
- med_tlv_select = dict(med_tlv_select)
- if med_tlv_select.get('inventory_management'):
- add_command_to_config_list(interface, 'lldp med-tlv-select inventory-management', commands)
- if tlv_select:
- tlv_select = dict(tlv_select)
- if tlv_select.get('power_management'):
- add_command_to_config_list(interface, 'lldp tlv-select power-management', commands)
-
- return commands
-
- def _clear_config(self, want, have):
- # Delete the interface config based on the want and have config
- commands = []
- if want.get('name'):
- interface = 'interface ' + want['name']
- else:
- interface = 'interface ' + have['name']
-
- if have.get('receive') and have.get('receive') != want.get('receive'):
- cmd = 'lldp receive'
- remove_command_from_config_list(interface, cmd, commands)
- if have.get('transmit') and have.get('transmit') != want.get('transmit'):
- cmd = 'lldp transmit'
- remove_command_from_config_list(interface, cmd, commands)
-
- return commands
diff --git a/lib/ansible/module_utils/network/ios/config/static_routes/static_routes.py b/lib/ansible/module_utils/network/ios/config/static_routes/static_routes.py
deleted file mode 100644
index 0e3eb4a66b..0000000000
--- a/lib/ansible/module_utils/network/ios/config/static_routes/static_routes.py
+++ /dev/null
@@ -1,532 +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 ios_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 copy
-from ansible.module_utils.six import iteritems
-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.ios.facts.facts import Facts
-from ansible.module_utils.network.ios.utils.utils import new_dict_to_set, validate_n_expand_ipv4, filter_dict_having_none_value
-
-
-class Static_Routes(ConfigBase):
- """
- The ios_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}
- commands = list()
- warnings = list()
-
- if self.state in self.ACTION_STATES:
- existing_static_routes_facts = self.get_static_routes_facts()
- else:
- existing_static_routes_facts = []
-
- if self.state in self.ACTION_STATES or self.state == 'rendered':
- commands.extend(self.set_config(existing_static_routes_facts))
-
- if commands and self.state in self.ACTION_STATES:
- if not self._module.check_mode:
- self._connection.edit_config(commands)
- result['changed'] = True
-
- if self.state in self.ACTION_STATES:
- result['commands'] = commands
-
- if self.state in self.ACTION_STATES or self.state == 'gathered':
- changed_static_routes_facts = self.get_static_routes_facts()
- elif self.state == 'rendered':
- result['rendered'] = commands
- elif self.state == 'parsed':
- running_config = self._module.params['running_config']
- if not running_config:
- self._module.fail_json(
- msg="value of running_config parameter must not be empty for state parsed"
- )
- result['parsed'] = self.get_static_routes_facts(data=running_config)
- 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
- """
- want = self._module.params['config']
- have = existing_static_routes_facts
- resp = self.set_state(want, have)
- return to_list(resp)
-
- def set_state(self, want, have):
- """ Select the appropriate function based on the state provided
-
- :param want: the desired configuration as a dictionary
- :param have: the current configuration as a dictionary
- :rtype: A list
- :returns: the commands necessary to migrate the current configuration
- to the desired configuration
- """
- state = self._module.params['state']
- if state in ('overridden', 'merged', 'replaced', 'rendered') and not want:
- self._module.fail_json(msg='value of config parameter must not be empty for state {0}'.format(state))
- commands = []
- if state == 'overridden':
- commands = self._state_overridden(want, have)
- elif state == 'deleted':
- commands = self._state_deleted(want, have)
- elif state == 'merged' or 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
- """
-
- commands = []
-
- # Drill each iteration of want n have and then based on dest and afi tyoe comparison take config call
- for w in want:
- for addr_want in w.get('address_families'):
- for route_want in addr_want.get('routes'):
- check = False
- for h in have:
- if h.get('address_families'):
- for addr_have in h.get('address_families'):
- for route_have in addr_have.get('routes'):
- if route_want.get('dest') == route_have.get('dest')\
- and addr_want['afi'] == addr_have['afi']:
- check = True
- have_set = set()
- new_hops = []
- for each in route_want.get('next_hops'):
- want_set = set()
- new_dict_to_set(each, [], want_set, 0)
- new_hops.append(want_set)
- new_dict_to_set(addr_have, [], have_set, 0)
- # Check if the have dict next_hops value is diff from want dict next_hops
- have_dict = filter_dict_having_none_value(route_want.get('next_hops')[0],
- route_have.get('next_hops')[0])
- # update the have_dict with forward_router_address
- have_dict.update({'forward_router_address': route_have.get('next_hops')[0].
- get('forward_router_address')})
- # updating the have_dict with next_hops val that's not None
- new_have_dict = {}
- for k, v in have_dict.items():
- if v is not None:
- new_have_dict.update({k: v})
-
- # Set the new config from the user provided want config
- cmd = self._set_config(w, h, addr_want, route_want, route_have, new_hops, have_set)
-
- if cmd:
- # since inplace update isn't allowed for static routes, preconfigured
- # static routes needs to be deleted before the new want static routes changes
- # are applied
- clear_route_have = copy.deepcopy(route_have)
- # inplace update is allowed in case of ipv6 static routes, so not deleting it
- # before applying the want changes
- if ':' not in route_want.get('dest'):
- commands.extend(self._clear_config({}, h, {}, addr_have,
- {}, clear_route_have))
- commands.extend(cmd)
- if check:
- break
- if check:
- break
- if not check:
- # For configuring any non-existing want config
- new_hops = []
- for each in route_want.get('next_hops'):
- want_set = set()
- new_dict_to_set(each, [], want_set, 0)
- new_hops.append(want_set)
- commands.extend(self._set_config(w, {}, addr_want, route_want, {}, new_hops, set()))
- commands = [each for each in commands if 'no' in each] + \
- [each for each in commands if 'no' not in each]
-
- return commands
-
- def _state_overridden(self, want, have):
- """ The command generator when state is overridden
-
- :rtype: A list
- :returns: the commands necessary to migrate the current configuration
- to the desired configuration
- """
-
- commands = []
- # Creating a copy of want, so that want dict is intact even after delete operation
- # performed during override want n have comparison
- temp_want = copy.deepcopy(want)
-
- # Drill each iteration of want n have and then based on dest and afi tyoe comparison take config call
- for h in have:
- if h.get('address_families'):
- for addr_have in h.get('address_families'):
- for route_have in addr_have.get('routes'):
- check = False
- for w in temp_want:
- for addr_want in w.get('address_families'):
- count = 0
- for route_want in addr_want.get('routes'):
- if route_want.get('dest') == route_have.get('dest') \
- and addr_want['afi'] == addr_have['afi']:
- check = True
- have_set = set()
- new_hops = []
- for each in route_want.get('next_hops'):
- want_set = set()
- new_dict_to_set(each, [], want_set, 0)
- new_hops.append(want_set)
- new_dict_to_set(addr_have, [], have_set, 0)
- commands.extend(self._clear_config(w, h, addr_want, addr_have,
- route_want, route_have))
- commands.extend(self._set_config(w, h, addr_want,
- route_want, route_have, new_hops, have_set))
- del addr_want.get('routes')[count]
- count += 1
- if check:
- break
- if check:
- break
- if not check:
- commands.extend(self._clear_config({}, h, {}, addr_have, {}, route_have))
- # For configuring any non-existing want config
- for w in temp_want:
- for addr_want in w.get('address_families'):
- for route_want in addr_want.get('routes'):
- new_hops = []
- for each in route_want.get('next_hops'):
- want_set = set()
- new_dict_to_set(each, [], want_set, 0)
- new_hops.append(want_set)
- commands.extend(self._set_config(w, {}, addr_want, route_want, {}, new_hops, set()))
- # Arranging the cmds suct that all delete cmds are fired before all set cmds
- commands = [each for each in sorted(commands) if 'no' in each] + \
- [each for each in sorted(commands) if 'no' not in each]
-
- return commands
-
- def _state_merged(self, want, have):
- """ The command generator when state is merged
-
- :rtype: A list
- :returns: the commands necessary to merge the provided into
- the current configuration
- """
- commands = []
-
- # Drill each iteration of want n have and then based on dest and afi tyoe comparison take config call
- for w in want:
- for addr_want in w.get('address_families'):
- for route_want in addr_want.get('routes'):
- check = False
- for h in have:
- if h.get('address_families'):
- for addr_have in h.get('address_families'):
- for route_have in addr_have.get('routes'):
- if route_want.get('dest') == route_have.get('dest')\
- and addr_want['afi'] == addr_have['afi']:
- check = True
- have_set = set()
- new_hops = []
- for each in route_want.get('next_hops'):
- want_set = set()
- new_dict_to_set(each, [], want_set, 0)
- new_hops.append(want_set)
- new_dict_to_set(addr_have, [], have_set, 0)
- commands.extend(self._set_config(w, h, addr_want,
- route_want, route_have, new_hops, have_set))
- if check:
- break
- if check:
- break
- if not check:
- # For configuring any non-existing want config
- new_hops = []
- for each in route_want.get('next_hops'):
- want_set = set()
- new_dict_to_set(each, [], want_set, 0)
- new_hops.append(want_set)
- commands.extend(self._set_config(w, {}, addr_want, route_want, {}, new_hops, set()))
-
- return commands
-
- def _state_deleted(self, want, have):
- """ The command generator when state is deleted
-
- :rtype: A list
- :returns: the commands necessary to remove the current configuration
- of the provided objects
- """
- commands = []
-
- if want:
- # Drill each iteration of want n have and then based on dest and afi type comparison fire delete config call
- for w in want:
- if w.get('address_families'):
- for addr_want in w.get('address_families'):
- for route_want in addr_want.get('routes'):
- check = False
- for h in have:
- if h.get('address_families'):
- for addr_have in h.get('address_families'):
- for route_have in addr_have.get('routes'):
- if route_want.get('dest') == route_have.get('dest') \
- and addr_want['afi'] == addr_have['afi']:
- check = True
- if route_want.get('next_hops'):
- commands.extend(self._clear_config({}, w, {}, addr_want, {}, route_want))
- else:
- commands.extend(self._clear_config({}, h, {}, addr_have, {}, route_have))
- if check:
- break
- if check:
- break
- else:
- for h in have:
- for addr_have in h.get('address_families'):
- for route_have in addr_have.get('routes'):
- if w.get('vrf') == h.get('vrf'):
- commands.extend(self._clear_config({}, h, {}, addr_have, {}, route_have))
- else:
- # Drill each iteration of have and then based on dest and afi type comparison fire delete config call
- for h in have:
- for addr_have in h.get('address_families'):
- for route_have in addr_have.get('routes'):
- commands.extend(self._clear_config({}, h, {}, addr_have, {}, route_have))
-
- return commands
-
- def prepare_config_commands(self, config_dict, cmd):
- """
- function to parse the input dict and form the prepare the config commands
- :rtype: A str
- :returns: The command necessary to configure the static routes
- """
-
- dhcp = config_dict.get('dhcp')
- distance_metric = config_dict.get('distance_metric')
- forward_router_address = config_dict.get('forward_router_address')
- global_route_config = config_dict.get('global')
- interface = config_dict.get('interface')
- multicast = config_dict.get('multicast')
- name = config_dict.get('name')
- permanent = config_dict.get('permanent')
- tag = config_dict.get('tag')
- track = config_dict.get('track')
- dest = config_dict.get('dest')
- temp_dest = dest.split('/')
- if temp_dest and ':' not in dest:
- dest = validate_n_expand_ipv4(self._module, {'address': dest})
-
- cmd = cmd + dest
- if interface:
- cmd = cmd + ' {0}'.format(interface)
- if forward_router_address:
- cmd = cmd + ' {0}'.format(forward_router_address)
- if dhcp:
- cmd = cmd + ' DHCP'
- if distance_metric:
- cmd = cmd + ' {0}'.format(distance_metric)
- if global_route_config:
- cmd = cmd + ' global'
- if multicast:
- cmd = cmd + ' multicast'
- if name:
- cmd = cmd + ' name {0}'.format(name)
- if permanent:
- cmd = cmd + ' permanent'
- elif track:
- cmd = cmd + ' track {0}'.format(track)
- if tag:
- cmd = cmd + ' tag {0}'.format(tag)
-
- return cmd
-
- def _set_config(self, want, have, addr_want, route_want, route_have, hops, have_set):
- """
- Set the interface config based on the want and have config
- :rtype: A list
- :returns: The commands necessary to configure the static routes
- """
-
- commands = []
- cmd = None
-
- vrf_diff = False
- topology_diff = False
- want_vrf = want.get('vrf')
- have_vrf = have.get('vrf')
- if want_vrf != have_vrf:
- vrf_diff = True
- want_topology = want.get('topology')
- have_topology = have.get('topology')
- if want_topology != have_topology:
- topology_diff = True
-
- have_dest = route_have.get('dest')
- if have_dest:
- have_set.add(tuple(iteritems({'dest': have_dest})))
-
- # configure set cmd for each hops under the same destination
- for each in hops:
- diff = each - have_set
- if vrf_diff:
- each.add(tuple(iteritems({'vrf': want_vrf})))
- if topology_diff:
- each.add(tuple(iteritems({'topology': want_topology})))
- if diff or vrf_diff or topology_diff:
- if want_vrf and not vrf_diff:
- each.add(tuple(iteritems({'vrf': want_vrf})))
- if want_topology and not vrf_diff:
- each.add(tuple(iteritems({'topology': want_topology})))
- each.add(tuple(iteritems({'afi': addr_want.get('afi')})))
- each.add(tuple(iteritems({'dest': route_want.get('dest')})))
- temp_want = {}
- for each_want in each:
- temp_want.update(dict(each_want))
-
- if temp_want.get('afi') == 'ipv4':
- cmd = 'ip route '
- vrf = temp_want.get('vrf')
- if vrf:
- cmd = cmd + 'vrf {0} '.format(vrf)
- cmd = self.prepare_config_commands(temp_want, cmd)
- elif temp_want.get('afi') == 'ipv6':
- cmd = 'ipv6 route '
- cmd = self.prepare_config_commands(temp_want, cmd)
- commands.append(cmd)
-
- return commands
-
- def _clear_config(self, want, have, addr_want, addr_have, route_want, route_have):
- """
- Delete the interface config based on the want and have config
- :rtype: A list
- :returns: The commands necessary to configure the static routes
- """
-
- commands = []
- cmd = None
-
- vrf_diff = False
- topology_diff = False
- want_vrf = want.get('vrf')
- have_vrf = have.get('vrf')
- if want_vrf != have_vrf:
- vrf_diff = True
- want_topology = want.get('topology')
- have_topology = have.get('topology')
- if want_topology != have_topology:
- topology_diff = True
-
- want_set = set()
- new_dict_to_set(addr_want, [], want_set, 0)
-
- have_hops = []
- for each in route_have.get('next_hops'):
- temp_have_set = set()
- new_dict_to_set(each, [], temp_have_set, 0)
- have_hops.append(temp_have_set)
-
- # configure delete cmd for each hops under the same destination
- for each in have_hops:
- diff = each - want_set
- if vrf_diff:
- each.add(tuple(iteritems({'vrf': have_vrf})))
- if topology_diff:
- each.add(tuple(iteritems({'topology': want_topology})))
- if diff or vrf_diff or topology_diff:
- if want_vrf and not vrf_diff:
- each.add(tuple(iteritems({'vrf': want_vrf})))
- if want_topology and not vrf_diff:
- each.add(tuple(iteritems({'topology': want_topology})))
- if addr_want:
- each.add(tuple(iteritems({'afi': addr_want.get('afi')})))
- else:
- each.add(tuple(iteritems({'afi': addr_have.get('afi')})))
- if route_want:
- each.add(tuple(iteritems({'dest': route_want.get('dest')})))
- else:
- each.add(tuple(iteritems({'dest': route_have.get('dest')})))
- temp_want = {}
- for each_want in each:
- temp_want.update(dict(each_want))
-
- if temp_want.get('afi') == 'ipv4':
- cmd = 'no ip route '
- vrf = temp_want.get('vrf')
- if vrf:
- cmd = cmd + 'vrf {0} '.format(vrf)
- cmd = self.prepare_config_commands(temp_want, cmd)
- elif temp_want.get('afi') == 'ipv6':
- cmd = 'no ipv6 route '
- cmd = self.prepare_config_commands(temp_want, cmd)
- commands.append(cmd)
-
- return commands
diff --git a/lib/ansible/module_utils/network/ios/config/vlans/vlans.py b/lib/ansible/module_utils/network/ios/config/vlans/vlans.py
deleted file mode 100644
index d77e298770..0000000000
--- a/lib/ansible/module_utils/network/ios/config/vlans/vlans.py
+++ /dev/null
@@ -1,292 +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 ios_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
-from ansible.module_utils.network.ios.facts.facts import Facts
-from ansible.module_utils.network.ios.utils.utils import dict_to_set
-
-
-class Vlans(ConfigBase):
- """
- The ios_vlans class
- """
-
- gather_subset = [
- '!all',
- '!min',
- ]
-
- gather_network_resources = [
- 'vlans',
- ]
-
- def __init__(self, module):
- super(Vlans, self).__init__(module)
-
- 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('vlans')
- 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']
- if state in ('overridden', 'merged', 'replaced') and not want:
- self._module.fail_json(msg='value of config parameter must not be empty for state {0}'.format(state))
-
- if state == 'overridden':
- commands = self._state_overridden(want, have, state)
- elif state == 'deleted':
- commands = self._state_deleted(want, have, state)
- elif state == 'merged':
- commands = self._state_merged(want, have)
- elif state == 'replaced':
- commands = self._state_replaced(want, have)
- return commands
-
- def _state_replaced(self, want, have):
- """ The command generator when state is replaced
-
- :rtype: A list
- :returns: the commands necessary to migrate the current configuration
- to the desired configuration
- """
- commands = []
-
- check = False
- for each in want:
- for every in have:
- if every['vlan_id'] == each['vlan_id']:
- check = True
- break
- else:
- continue
- if check:
- commands.extend(self._set_config(each, every))
- else:
- commands.extend(self._set_config(each, dict()))
-
- return commands
-
- def _state_overridden(self, want, have, state):
- """ The command generator when state is overridden
-
- :rtype: A list
- :returns: the commands necessary to migrate the current configuration
- to the desired configuration
- """
- commands = []
-
- want_local = want
- for each in have:
- count = 0
- for every in want_local:
- if each['vlan_id'] == every['vlan_id']:
- break
- count += 1
- else:
- # We didn't find a matching desired state, which means we can
- # pretend we received an empty desired state.
- commands.extend(self._clear_config(every, each, state))
- continue
- commands.extend(self._set_config(every, each))
- # as the pre-existing VLAN are now configured by
- # above set_config call, deleting the respective
- # VLAN entry from the want_local list
- del want_local[count]
-
- # Iterating through want_local list which now only have new VLANs to be
- # configured
- for each in want_local:
- commands.extend(self._set_config(each, dict()))
-
- return commands
-
- def _state_merged(self, want, have):
- """ The command generator when state is merged
-
- :rtype: A list
- :returns: the commands necessary to merge the provided into
- the current configuration
- """
- commands = []
-
- check = False
- for each in want:
- for every in have:
- if each.get('vlan_id') == every.get('vlan_id'):
- check = True
- break
- else:
- continue
- if check:
- commands.extend(self._set_config(each, every))
- else:
- commands.extend(self._set_config(each, dict()))
-
- return commands
-
- def _state_deleted(self, want, have, state):
- """ The command generator when state is deleted
-
- :rtype: A list
- :returns: the commands necessary to remove the current configuration
- of the provided objects
- """
- commands = []
-
- if want:
- check = False
- for each in want:
- for every in have:
- if each.get('vlan_id') == every.get('vlan_id'):
- check = True
- break
- else:
- check = False
- continue
- if check:
- commands.extend(self._clear_config(each, every, state))
- else:
- for each in have:
- commands.extend(self._clear_config(dict(), each, state))
-
- return commands
-
- def remove_command_from_config_list(self, vlan, cmd, commands):
- if vlan not in commands and cmd != 'vlan':
- commands.insert(0, vlan)
- elif cmd == 'vlan':
- commands.append('no %s' % vlan)
- return commands
- commands.append('no %s' % cmd)
- return commands
-
- def add_command_to_config_list(self, vlan_id, cmd, commands):
- if vlan_id not in commands:
- commands.insert(0, vlan_id)
- if cmd not in commands:
- commands.append(cmd)
-
- def _set_config(self, want, have):
- # Set the interface config based on the want and have config
- commands = []
- vlan = 'vlan {0}'.format(want.get('vlan_id'))
-
- # Get the diff b/w want n have
- want_dict = dict_to_set(want)
- have_dict = dict_to_set(have)
- diff = want_dict - have_dict
-
- if diff:
- name = dict(diff).get('name')
- state = dict(diff).get('state')
- shutdown = dict(diff).get('shutdown')
- mtu = dict(diff).get('mtu')
- remote_span = dict(diff).get('remote_span')
- if name:
- cmd = 'name {0}'.format(name)
- self.add_command_to_config_list(vlan, cmd, commands)
- if state:
- cmd = 'state {0}'.format(state)
- self.add_command_to_config_list(vlan, cmd, commands)
- if mtu:
- cmd = 'mtu {0}'.format(mtu)
- self.add_command_to_config_list(vlan, cmd, commands)
- if remote_span:
- self.add_command_to_config_list(vlan, 'remote-span', commands)
- if shutdown == 'enabled':
- self.add_command_to_config_list(vlan, 'shutdown', commands)
- elif shutdown == 'disabled':
- self.add_command_to_config_list(vlan, 'no shutdown', commands)
-
- return commands
-
- def _clear_config(self, want, have, state):
- # Delete the interface config based on the want and have config
- commands = []
- vlan = 'vlan {0}'.format(have.get('vlan_id'))
-
- if have.get('vlan_id') and 'default' not in have.get('name')\
- and (have.get('vlan_id') != want.get('vlan_id') or state == 'deleted'):
- self.remove_command_from_config_list(vlan, 'vlan', commands)
- elif 'default' not in have.get('name'):
- if have.get('mtu') != want.get('mtu'):
- self.remove_command_from_config_list(vlan, 'mtu', commands)
- if have.get('remote_span') != want.get('remote_span') and want.get('remote_span'):
- self.remove_command_from_config_list(vlan, 'remote-span', commands)
- if have.get('shutdown') != want.get('shutdown') and want.get('shutdown'):
- self.remove_command_from_config_list(vlan, 'shutdown', commands)
- if have.get('state') != want.get('state') and want.get('state'):
- self.remove_command_from_config_list(vlan, 'state', commands)
-
- return commands
diff --git a/lib/ansible/module_utils/network/ios/facts/acl_interfaces/acl_interfaces.py b/lib/ansible/module_utils/network/ios/facts/acl_interfaces/acl_interfaces.py
deleted file mode 100644
index c80939aeba..0000000000
--- a/lib/ansible/module_utils/network/ios/facts/acl_interfaces/acl_interfaces.py
+++ /dev/null
@@ -1,122 +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 ios_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.ios.utils.utils import get_interface_type
-from ansible.module_utils.network.ios.argspec.acl_interfaces.acl_interfaces import Acl_InterfacesArgs
-
-
-class Acl_InterfacesFacts(object):
- """ The ios_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_acl_interfaces_data(self, connection):
- return connection.get('sh running-config | include interface|ip access-group|ipv6 traffic-filter')
-
- def populate_facts(self, connection, ansible_facts, data=None):
- """ Populate the facts for interfaces
- :param connection: the device connection
- :param ansible_facts: Facts dictionary
- :param data: previously collected conf
- :rtype: dictionary
- :returns: facts
- """
- objs = []
-
- if not data:
- data = self.get_acl_interfaces_data(connection)
- # operate on a collection of resource x
- config = data.split('interface ')
- for conf in config:
- if conf:
- obj = self.render_config(self.generated_spec, conf)
- if obj:
- objs.append(obj)
-
- facts = {}
- if objs:
- facts['acl_interfaces'] = []
- params = utils.validate_config(self.argument_spec, {'config': objs})
-
- for cfg in params['config']:
- facts['acl_interfaces'].append(utils.remove_empties(cfg))
- ansible_facts['ansible_network_resources'].update(facts)
-
- return ansible_facts
-
- def render_config(self, spec, conf):
- """
- Render config as dictionary structure and delete keys
- from spec for null values
-
- :param spec: The facts tree, generated from the argspec
- :param conf: The configuration
- :rtype: dictionary
- :returns: The generated config
- """
- config = deepcopy(spec)
- match = re.search(r'^(\S+)', conf)
- intf = match.group(1)
-
- if get_interface_type(intf) == 'unknown':
- return {}
- config['name'] = intf
- config['access_groups'] = []
- acl_v4_config = {}
- acl_v6_config = {}
-
- def common_iter_code(cmd, conf):
- # Common code for IPV4 and IPV6 config parsing
- acls = []
- re_cmd = cmd + ' (\\S+.*)'
- ip_all = re.findall(re_cmd, conf)
- for each in ip_all:
- acl = {}
- access_grp_config = each.split(' ')
- acl['name'] = access_grp_config[0]
- acl['direction'] = access_grp_config[1]
- acls.append(acl)
- return acls
-
- if 'ip' in conf:
- acls = common_iter_code('ip access-group', conf)
- acl_v4_config['afi'] = 'ipv4'
- acl_v4_config['acls'] = acls
- config['access_groups'].append(acl_v4_config)
- if 'ipv6' in conf:
- acls = common_iter_code('ipv6 traffic-filter', conf)
- acl_v6_config['afi'] = 'ipv6'
- acl_v6_config['acls'] = acls
- config['access_groups'].append(acl_v6_config)
-
- return utils.remove_empties(config)
diff --git a/lib/ansible/module_utils/network/ios/facts/acls/acls.py b/lib/ansible/module_utils/network/ios/facts/acls/acls.py
deleted file mode 100644
index 3b99a18f5c..0000000000
--- a/lib/ansible/module_utils/network/ios/facts/acls/acls.py
+++ /dev/null
@@ -1,498 +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 ios_acls fact class
-It is in this file the configuration is collected from the device
-for a given resource, parsed, and the facts tree is populated
-based on the configuration.
-"""
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-from copy import deepcopy
-import re
-from ansible.module_utils.network.common import utils
-from ansible.module_utils.network.ios.utils.utils import check_n_return_valid_ipv6_addr
-from ansible.module_utils.network.ios.argspec.acls.acls import AclsArgs
-
-
-class AclsFacts(object):
- """ The ios_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_acl_data(self, connection):
- # Get the access-lists from the ios router
- return connection.get('sh 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_acl_data(connection)
- # operate on a collection of resource x
- config = data.split('\n')
- spec = {'acls': list(), 'afi': None}
- if config:
- objs = self.render_config(spec, config)
- # check if rendered config list has only empty dict
- if len(objs) == 1 and objs[0] == {}:
- objs = []
- 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 create_config_dict(self, config):
- """ Function that parse the acls config and convert to module usable config
- :param config: config
- :rtype: A dict
- :returns: the config generated based on have config params
- """
- conf = {}
- temp_list = []
- access_list_name = ''
- count = 0
- if len(config) >= 1 and config[0] != '':
- for each in config:
- if 'access-list' in each:
- temp = each.split('access-list ')[1].split(' ')[0]
- if temp == 'extended' or temp == 'standard':
- temp = each.split('access-list ')[1]
- if not access_list_name:
- access_list_name = temp
- if 'access-list' not in each:
- if 'extended' in temp or 'standard' in temp:
- temp_list.append('ipv4 access-list ' + temp + each)
- else:
- temp_list.append('ipv6 access-list ' + temp + each)
- if temp == access_list_name and 'access-list' in each and \
- not ('extended' in access_list_name or 'standard' in access_list_name):
- temp_list.append(each)
- elif temp != access_list_name:
- conf[access_list_name] = temp_list
- temp_list = list()
- if 'permit' in each or 'deny' in each:
- temp_list.append(each)
- access_list_name = temp
- count += 1
- if len(config) == count:
- conf[access_list_name] = temp_list
- temp_list = []
- return conf
-
- def populate_port_protocol(self, source, destination, each_list):
- """ Function Populates port portocol wrt to source and destination
- :param acls: source config
- :param config: destination config
- :param each_list: config
- :rtype: A list
- :returns: the commands generated based on source and destination params
- """
- operators = ['eq', 'gt', 'lt', 'neq', 'range']
- for item in operators:
- if item in each_list:
- index = each_list.index(item)
- if source.get('address') or source.get('any') or source.get('host') and not source.get('port_protocol'):
- try:
- source_index = each_list.index(source.get('address'))
- except ValueError:
- try:
- source_index = each_list.index('any')
- except ValueError:
- source_index = each_list.index('host')
- if source.get('address'):
- if (source_index + 2) == index and 'ipv6' not in each_list:
- source['port_protocol'] = {item: each_list[index + 1]}
- each_list.remove(item)
- del each_list[index]
- elif (source_index + 1) == index and 'ipv6' in each_list:
- source['port_protocol'] = {item: each_list[index + 1]}
- each_list.remove(item)
- del each_list[source_index]
- del each_list[index - 1]
- elif source.get('any'):
- if (source_index + 1) == index:
- source['port_protocol'] = {item: each_list[index + 1]}
- each_list.remove(item)
- del each_list[index - 1]
- del each_list[source_index]
- elif source.get('host'):
- if (source_index + 1) == index:
- source['port_protocol'] = {item: each_list[index + 1]}
- each_list.remove(item)
- del each_list[index - 1]
- del each_list[source_index]
- if destination.get('address') or destination.get('any') or destination.get('host'):
- try:
- destination_index = each_list.index(destination.get('address'))
- except ValueError:
- try:
- destination_index = each_list.index('any')
- except ValueError:
- destination_index = each_list.index('host') + 1
- index -= 1
- if (destination_index + 1) == index or (destination_index + 2) == index:
- destination['port_protocol'] = {item: each_list[index + 1]}
- each_list.remove(item)
- del each_list[index]
- break
- if 'eq' in each_list or 'gt' in each_list or 'lt' in each_list or 'neq' in each_list or 'range' in each_list:
- self.populate_port_protocol(source, destination, each_list)
-
- def populate_source_destination(self, each, config, source, destination):
- any = []
- if 'any' in each:
- any = re.findall('any', each)
- if len(any) == 2:
- source['any'] = True
- destination['any'] = True
- elif 'host' in each:
- host = re.findall('host', each)
- each = each.split(' ')
- if len(host) == 2:
- host_index = each.index('host')
- source['host'] = each[host_index + 1]
- del each[host_index]
- host_index = each.index('host')
- destination['host'] = each[host_index + 1]
- else:
- ip_n_wildcard_bits = re.findall(r'[0-9]+(?:\.[0-9]+){3}', each)
- ip_index = None
- if ip_n_wildcard_bits:
- ip_index = each.index(ip_n_wildcard_bits[0])
- host_index = each.index('host')
- if ip_index:
- if host_index < ip_index:
- source['host'] = each(host_index + 1)
- destination['address'] = ip_n_wildcard_bits[0]
- destination['wildcard_bits'] = ip_n_wildcard_bits[1]
- elif host_index > ip_index:
- destination['host'] = each(host_index + 1)
- source['address'] = ip_n_wildcard_bits[0]
- source['wildcard_bits'] = ip_n_wildcard_bits[1]
- else:
- if config['afi'] == 'ipv4':
- ip_n_wildcard_bits = re.findall(r'[0-9]+(?:\.[0-9]+){3}', each)
- each = each.split(' ')
- if len(ip_n_wildcard_bits) == 0 and len(any) == 1:
- source['any'] = True
- elif len(ip_n_wildcard_bits) == 1:
- source['address'] = ip_n_wildcard_bits[0]
- elif len(ip_n_wildcard_bits) == 2:
- if 'any' in each:
- if each.index('any') > each.index(ip_n_wildcard_bits[0]):
- source['address'] = ip_n_wildcard_bits[0]
- source['wildcard_bits'] = ip_n_wildcard_bits[1]
- destination['any'] = True
- elif each.index('any') < each.index(ip_n_wildcard_bits[0]):
- source['any'] = True
- destination['address'] = ip_n_wildcard_bits[0]
- destination['wildcard_bits'] = ip_n_wildcard_bits[1]
- else:
- source['address'] = ip_n_wildcard_bits[0]
- source['wildcard_bits'] = ip_n_wildcard_bits[1]
- elif len(ip_n_wildcard_bits) == 4:
- source['address'] = ip_n_wildcard_bits[0]
- source['wildcard_bits'] = ip_n_wildcard_bits[1]
- destination['address'] = ip_n_wildcard_bits[2]
- destination['wildcard_bits'] = ip_n_wildcard_bits[3]
- elif config['afi'] == 'ipv6':
- temp_ipv6 = []
- each = each.split(' ')
- check_n_return_valid_ipv6_addr(self._module, each, temp_ipv6)
- count = 0
- for every in each:
- if len(temp_ipv6) == 2:
- if temp_ipv6[0] in every or temp_ipv6[1] in every:
- temp_ipv6[count] = every
- count += 1
- elif len(temp_ipv6) == 1:
- if temp_ipv6[0] in every:
- temp_ipv6[count] = every
- if 'any' in each:
- if each.index('any') > each.index(temp_ipv6[0]):
- source['address'] = temp_ipv6[0]
- destination['any'] = True
- elif each.index('any') < each.index(temp_ipv6[0]):
- source['any'] = True
- destination['address'] = temp_ipv6[0]
- elif len(temp_ipv6) == 2:
- source['address'] = temp_ipv6[0]
- destination['address'] = temp_ipv6[1]
-
- def parsed_config_facts(self, have_config):
- """
- For parsed config have_config is string of commands which
- need to be splitted before passing it through render_config
- from spec for null values
- :param have_config: The configuration
- :rtype: list of have config
- :returns: The splitted generated config
- """
- split_config = re.split('ip|ipv6 access-list', have_config[0])
- temp_config = []
-
- # common piece of code for populating the temp_config list
- def common_config_code(each, grant, temp_config):
- temp = re.split(grant, each)
- temp_config.append(temp[0])
- temp_config.extend([grant + item for item in temp if 'access-list' not in item])
-
- for each in split_config:
- if 'v6' in each:
- each = 'ipv6 ' + each.split('v6 ')[1]
- if 'permit' in each:
- common_config_code(each, 'permit', temp_config)
- elif 'deny' in each:
- common_config_code(each, 'deny', temp_config)
- else:
- each = 'ip' + each
- if 'permit' in each:
- common_config_code(each, 'permit', temp_config)
- if 'deny' in each:
- common_config_code(each, 'deny', temp_config)
- return temp_config
-
- def render_config(self, spec, have_config):
- """
- 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
- """
-
- # for parsed scnenario where commands are passed to generate the acls facts
- if len(have_config) == 1:
- have_config = self.parsed_config_facts(have_config)
-
- config = deepcopy(spec)
- render_config = list()
- acls = dict()
- aces = list()
- temp_name = ''
- for each in have_config:
- each_list = [val for val in each.split(' ') if val != '']
- if 'IPv6' in each or 'ipv6' in each:
- if aces:
- config['acls'].append(acls)
- ip_config = config
- if ip_config.get('acls'):
- render_config.append(ip_config)
- if not config['afi'] or config['afi'] == 'ipv4':
- config = deepcopy(spec)
- config['afi'] = 'ipv6'
- acls = dict()
- aces = list()
- elif not config['afi'] and ('IP' in each or 'ip' in each):
- config['afi'] = 'ipv4'
- if 'access list' in each or 'access-list' in each:
- try:
- temp_index = each_list.index('list')
- name = (each_list[temp_index + 1])
- except ValueError:
- name = each_list[-1]
- if temp_name != name:
- if aces:
- config['acls'].append(acls)
- acls = dict()
- aces = list()
- temp_name = name
- acls['name'] = name
- if 'Extended' in each:
- acls['acl_type'] = 'extended'
- continue
- elif 'Standard' in each:
- acls['acl_type'] = 'standard'
- continue
- ace_options = {}
- try:
- if config['afi'] == 'ipv4':
- if 'deny' in each_list or 'permit' in each_list:
- ace_options['sequence'] = int(each_list[0])
- elif config['afi'] == 'ipv6':
- if 'sequence' in each_list:
- ace_options['sequence'] = int(each_list[each_list.index('sequence') + 1])
- except ValueError:
- pass
- if utils.parse_conf_arg(each, 'permit'):
- ace_options['grant'] = 'permit'
- each_list.remove('permit')
- elif utils.parse_conf_arg(each, 'deny'):
- ace_options['grant'] = 'deny'
- each_list.remove('deny')
-
- protocol_option = ['ahp', 'eigrp', 'esp', 'gre', 'hbh', 'icmp', 'igmp', 'ip', 'ipv6', 'ipinip', 'nos',
- 'ospf', 'pcp', 'pim', 'sctp', 'tcp', 'udp']
- tcp_flags = ['ack', 'established', 'fin', 'psh', 'rst', 'syn', 'urg']
- icmp_options = ['administratively_prohibited', 'alternate_address', 'conversion_error',
- 'dod_host_prohibited', 'dod_net_prohibited', 'echo', 'echo_reply',
- 'general_parameter_problem', 'host_isolated', 'host_precedence_unreachable',
- 'host_redirect', 'host_tos_redirect', 'host_tos_unreachable', 'host_unknown',
- 'host_unreachable', 'information_reply', 'information_request', 'mask_reply',
- 'mask_request', 'mobile_redirect', 'net_redirect', 'net_tos_redirect',
- 'net_tos_unreachable', 'net_unreachable', 'network_unknown', 'no_room_for_option',
- 'option_missing', 'packet_too_big', 'parameter_problem', 'port_unreachable',
- 'precedence_unreachable', 'protocol_unreachable', 'reassembly_timeout', 'redirect',
- 'router_advertisement', 'router_solicitation', 'source_quench', 'source_route_failed',
- 'time_exceeded', 'timestamp_reply', 'timestamp_request', 'traceroute', 'ttl_exceeded',
- 'unreachable']
- igmp_options = ['dvmrp', 'host_query', 'mtrace_resp', 'mtrace_route', 'pim', 'trace', 'v1host_report',
- 'v2host_report', 'v2leave_group', 'v3host_report']
-
- temp_option = ''
- for option in protocol_option:
- if option in each_list and 'access' not in each_list[each_list.index(option) + 1]:
- temp_option = option
- each_list.remove(temp_option)
- if temp_option == 'tcp':
- temp_flag = [each_flag for each_flag in tcp_flags if each_flag in each]
- if temp_flag:
- flag = temp_flag[0]
- if flag in each_list:
- each_list.remove(flag)
- temp_flag = flag
- if temp_option == 'icmp':
- temp_flag = [each_option for each_option in icmp_options if each_option in each]
- if temp_flag:
- flag = temp_flag[0]
- if flag in each_list:
- each_list.remove(flag)
- temp_flag = flag
- if temp_option == 'igmp':
- temp_flag = [each_option for each_option in igmp_options if each_option in each]
- if temp_flag:
- flag = temp_flag[0]
- if flag in each_list:
- each_list.remove(flag)
- temp_flag = flag
- break
-
- dscp = utils.parse_conf_arg(each, 'dscp')
- if dscp:
- ace_options['dscp'] = dscp.split(' ')[0]
- fragments = utils.parse_conf_arg(each, 'fragments')
- if fragments:
- ace_options['fragments'] = fragments.split(' ')[0]
- log = utils.parse_conf_arg(each, 'log')
- if log:
- ace_options['log'] = log.split(' ')[0]
- log_input = utils.parse_conf_arg(each, 'log_input')
- if log_input:
- ace_options['log_input'] = log_input.split(' ')[0]
- option = utils.parse_conf_arg(each, 'option')
- if option:
- option = option.split(' ')[0]
- option_dict = {}
- option_dict[option] = True
- ace_options['option'] = option_dict
- precedence = utils.parse_conf_arg(each, 'precedence')
- if precedence:
- ace_options['precedence'] = precedence.split(' ')[0]
- time_range = utils.parse_conf_arg(each, 'time_range')
- if time_range:
- ace_options['time_range'] = time_range.split(' ')[0]
- tos = utils.parse_conf_arg(each, 'tos')
- if tos:
- tos_val = dict()
- try:
- tos_val['service_value'] = int(tos)
- except ValueError:
- tos = tos.replace('-', '_')
- tos_val[tos] = True
- ace_options['tos'] = tos_val
- ttl = utils.parse_conf_arg(each, 'ttl')
- if ttl:
- temp_ttl = ttl.split(' ')
- ttl = {}
- ttl[temp_ttl[0]] = temp_ttl[1]
- each_list = [item for item in each_list[:each_list.index('ttl')]]
- ace_options['ttl'] = ttl
-
- source = {}
- destination = {}
- self.populate_source_destination(each, config, source, destination)
-
- if source.get('address') and source.get('address') == destination.get('address'):
- self._module.fail_json(msg='Source and Destination address cannot be same!')
- else:
- self.populate_port_protocol(source, destination, each_list)
-
- if source:
- ace_options['source'] = source
- if destination:
- ace_options['destination'] = destination
- if temp_option:
- protocol_options = {}
- ace_options['protocol'] = temp_option
- if temp_option == 'tcp':
- tcp = {}
- if temp_flag:
- tcp[temp_flag] = True
- else:
- tcp['set'] = True
- protocol_options[temp_option] = tcp
- elif temp_option == 'icmp':
- icmp = dict()
- if temp_flag:
- icmp[temp_flag] = True
- else:
- icmp['set'] = True
- protocol_options[temp_option] = icmp
- elif temp_option == 'igmp':
- igmp = dict()
- if temp_flag:
- igmp[temp_flag] = True
- else:
- igmp['set'] = True
- protocol_options[temp_option] = igmp
- else:
- protocol_options[temp_option] = True
- ace_options['protocol_options'] = protocol_options
- if ace_options:
- aces.append(ace_options)
- acls['aces'] = aces
- if acls:
- if not config.get('acls'):
- config['acls'] = list()
- config['acls'].append(acls)
-
- if config not in render_config:
- render_config.append(utils.remove_empties(config))
- # delete the populated config
- del config
-
- return render_config
diff --git a/lib/ansible/module_utils/network/ios/facts/facts.py b/lib/ansible/module_utils/network/ios/facts/facts.py
deleted file mode 100644
index 8d66e87963..0000000000
--- a/lib/ansible/module_utils/network/ios/facts/facts.py
+++ /dev/null
@@ -1,79 +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 ios
-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.ios.facts.interfaces.interfaces import InterfacesFacts
-from ansible.module_utils.network.ios.facts.l2_interfaces.l2_interfaces import L2_InterfacesFacts
-from ansible.module_utils.network.ios.facts.vlans.vlans import VlansFacts
-from ansible.module_utils.network.ios.facts.lag_interfaces.lag_interfaces import Lag_interfacesFacts
-from ansible.module_utils.network.ios.facts.lacp.lacp import LacpFacts
-from ansible.module_utils.network.ios.facts.lacp_interfaces.lacp_interfaces import Lacp_InterfacesFacts
-from ansible.module_utils.network.ios.facts.lldp_global.lldp_global import Lldp_globalFacts
-from ansible.module_utils.network.ios.facts.lldp_interfaces.lldp_interfaces import Lldp_InterfacesFacts
-from ansible.module_utils.network.ios.facts.l3_interfaces.l3_interfaces import L3_InterfacesFacts
-from ansible.module_utils.network.ios.facts.acl_interfaces.acl_interfaces import Acl_InterfacesFacts
-from ansible.module_utils.network.ios.facts.static_routes.static_routes import Static_RoutesFacts
-from ansible.module_utils.network.ios.facts.acls.acls import AclsFacts
-from ansible.module_utils.network.ios.facts.legacy.base import Default, Hardware, Interfaces, Config
-
-
-FACT_LEGACY_SUBSETS = dict(
- default=Default,
- hardware=Hardware,
- interfaces=Interfaces,
- config=Config
-)
-
-FACT_RESOURCE_SUBSETS = dict(
- interfaces=InterfacesFacts,
- l2_interfaces=L2_InterfacesFacts,
- vlans=VlansFacts,
- lag_interfaces=Lag_interfacesFacts,
- lacp=LacpFacts,
- lacp_interfaces=Lacp_InterfacesFacts,
- lldp_global=Lldp_globalFacts,
- lldp_interfaces=Lldp_InterfacesFacts,
- l3_interfaces=L3_InterfacesFacts,
- acl_interfaces=Acl_InterfacesFacts,
- static_routes=Static_RoutesFacts,
- acls=AclsFacts,
-)
-
-
-class Facts(FactsBase):
- """ The fact class for ios
- """
-
- VALID_LEGACY_GATHER_SUBSETS = frozenset(FACT_LEGACY_SUBSETS.keys())
- VALID_RESOURCE_SUBSETS = frozenset(FACT_RESOURCE_SUBSETS.keys())
-
- def __init__(self, module):
- super(Facts, self).__init__(module)
-
- def get_facts(self, legacy_facts_type=None, resource_facts_type=None, data=None):
- """ Collect the facts for ios
- :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/ios/facts/interfaces/interfaces.py b/lib/ansible/module_utils/network/ios/facts/interfaces/interfaces.py
deleted file mode 100644
index a6802bd2e8..0000000000
--- a/lib/ansible/module_utils/network/ios/facts/interfaces/interfaces.py
+++ /dev/null
@@ -1,97 +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 ios 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.ios.utils.utils import get_interface_type, normalize_interface
-from ansible.module_utils.network.ios.argspec.interfaces.interfaces import InterfacesArgs
-
-
-class InterfacesFacts(object):
- """ The ios interfaces fact class
- """
-
- def __init__(self, module, subspec='config', options='options'):
- self._module = module
- self.argument_spec = InterfacesArgs.argument_spec
- spec = deepcopy(self.argument_spec)
- if subspec:
- if options:
- facts_argument_spec = spec[subspec][options]
- else:
- facts_argument_spec = spec[subspec]
- else:
- facts_argument_spec = spec
-
- self.generated_spec = utils.generate_dict(facts_argument_spec)
-
- def populate_facts(self, connection, ansible_facts, data=None):
- """ Populate the facts for interfaces
- :param connection: the device connection
- :param ansible_facts: Facts dictionary
- :param data: previously collected conf
- :rtype: dictionary
- :returns: facts
- """
- objs = []
-
- if not data:
- data = connection.get('show running-config | section ^interface')
- # operate on a collection of resource x
- config = data.split('interface ')
- for conf in config:
- if conf:
- obj = self.render_config(self.generated_spec, conf)
- if obj:
- objs.append(obj)
- facts = {}
-
- if objs:
- facts['interfaces'] = []
- params = utils.validate_config(self.argument_spec, {'config': objs})
- for cfg in params['config']:
- facts['interfaces'].append(utils.remove_empties(cfg))
- ansible_facts['ansible_network_resources'].update(facts)
-
- return ansible_facts
-
- def render_config(self, spec, conf):
- """
- Render config as dictionary structure and delete keys from spec for null values
-
- :param spec: The facts tree, generated from the argspec
- :param conf: The configuration
- :rtype: dictionary
- :returns: The generated config
- """
- config = deepcopy(spec)
- match = re.search(r'^(\S+)', conf)
- intf = match.group(1)
-
- if get_interface_type(intf) == 'unknown':
- return {}
- # populate the facts from the configuration
- config['name'] = normalize_interface(intf)
- config['description'] = utils.parse_conf_arg(conf, 'description')
- config['speed'] = utils.parse_conf_arg(conf, 'speed')
- if utils.parse_conf_arg(conf, 'mtu'):
- config['mtu'] = int(utils.parse_conf_arg(conf, 'mtu'))
- config['duplex'] = utils.parse_conf_arg(conf, 'duplex')
- enabled = utils.parse_conf_cmd_arg(conf, 'shutdown', False)
- config['enabled'] = enabled if enabled is not None else True
-
- return utils.remove_empties(config)
diff --git a/lib/ansible/module_utils/network/ios/facts/l2_interfaces/l2_interfaces.py b/lib/ansible/module_utils/network/ios/facts/l2_interfaces/l2_interfaces.py
deleted file mode 100644
index 8f6ddf2698..0000000000
--- a/lib/ansible/module_utils/network/ios/facts/l2_interfaces/l2_interfaces.py
+++ /dev/null
@@ -1,114 +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 ios 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.ios.utils.utils import get_interface_type, normalize_interface
-from ansible.module_utils.network.ios.argspec.l2_interfaces.l2_interfaces import L2_InterfacesArgs
-
-
-class L2_InterfacesFacts(object):
- """ The ios l2 interfaces fact class
- """
-
- def __init__(self, module, subspec='config', options='options'):
- self._module = module
- self.argument_spec = L2_InterfacesArgs.argument_spec
- spec = deepcopy(self.argument_spec)
- if subspec:
- if options:
- facts_argument_spec = spec[subspec][options]
- else:
- facts_argument_spec = spec[subspec]
- else:
- facts_argument_spec = spec
-
- self.generated_spec = utils.generate_dict(facts_argument_spec)
-
- def populate_facts(self, connection, ansible_facts, data=None):
- """ Populate the facts for interfaces
- :param connection: the device connection
- :param ansible_facts: Facts dictionary
- :param data: previously collected conf
- :rtype: dictionary
- :returns: facts
- """
- objs = []
-
- if not data:
- data = connection.get('show running-config | section ^interface')
- # operate on a collection of resource x
- config = data.split('interface ')
- for conf in config:
- if conf:
- obj = self.render_config(self.generated_spec, conf)
- if obj:
- objs.append(obj)
-
- facts = {}
- if objs:
- facts['l2_interfaces'] = []
- params = utils.validate_config(self.argument_spec, {'config': objs})
- for cfg in params['config']:
- facts['l2_interfaces'].append(utils.remove_empties(cfg))
- ansible_facts['ansible_network_resources'].update(facts)
-
- return ansible_facts
-
- def render_config(self, spec, conf):
- """
- Render config as dictionary structure and delete keys from spec for null values
- :param spec: The facts tree, generated from the argspec
- :param conf: The configuration
- :rtype: dictionary
- :returns: The generated config
- """
- config = deepcopy(spec)
- match = re.search(r'^(\S+)', conf)
- intf = match.group(1)
-
- if get_interface_type(intf) == 'unknown':
- return {}
-
- if intf.upper()[:2] in ('HU', 'FO', 'TW', 'TE', 'GI', 'FA', 'ET', 'PO'):
- # populate the facts from the configuration
- config['name'] = normalize_interface(intf)
- has_mode = utils.parse_conf_arg(conf, 'switchport mode')
- if has_mode:
- config['mode'] = has_mode
- has_access = utils.parse_conf_arg(conf, 'switchport access vlan')
- if has_access:
- config["access"] = {"vlan": int(has_access)}
-
- has_voice = utils.parse_conf_arg(conf, 'switchport voice vlan')
- if has_voice:
- config["voice"] = {"vlan": int(has_voice)}
-
- trunk = dict()
- trunk["encapsulation"] = utils.parse_conf_arg(conf, 'encapsulation')
- native_vlan = utils.parse_conf_arg(conf, 'native vlan')
- if native_vlan:
- trunk["native_vlan"] = int(native_vlan)
- allowed_vlan = utils.parse_conf_arg(conf, 'allowed vlan')
- if allowed_vlan:
- trunk["allowed_vlans"] = allowed_vlan.split(',')
- pruning_vlan = utils.parse_conf_arg(conf, 'pruning vlan')
- if pruning_vlan:
- trunk['pruning_vlans'] = pruning_vlan.split(',')
-
- config['trunk'] = trunk
-
- return utils.remove_empties(config)
diff --git a/lib/ansible/module_utils/network/ios/facts/l3_interfaces/l3_interfaces.py b/lib/ansible/module_utils/network/ios/facts/l3_interfaces/l3_interfaces.py
deleted file mode 100644
index 5afab57b37..0000000000
--- a/lib/ansible/module_utils/network/ios/facts/l3_interfaces/l3_interfaces.py
+++ /dev/null
@@ -1,124 +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 ios_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.ios.utils.utils import get_interface_type, normalize_interface
-from ansible.module_utils.network.ios.argspec.l3_interfaces.l3_interfaces import L3_InterfacesArgs
-
-
-class L3_InterfacesFacts(object):
- """ The ios 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 conf
- :rtype: dictionary
- :returns: facts
- """
- objs = []
-
- if not data:
- data = connection.get('show running-config | section ^interface')
- # operate on a collection of resource x
- config = data.split('interface ')
- for conf in config:
- if conf:
- obj = self.render_config(self.generated_spec, conf)
- if obj:
- objs.append(obj)
- facts = {}
-
- if objs:
- facts['l3_interfaces'] = []
- params = utils.validate_config(self.argument_spec, {'config': objs})
- for cfg in params['config']:
- facts['l3_interfaces'].append(utils.remove_empties(cfg))
- ansible_facts['ansible_network_resources'].update(facts)
-
- return ansible_facts
-
- def render_config(self, spec, conf):
- """
- Render config as dictionary structure and delete keys from spec for null values
- :param spec: The facts tree, generated from the argspec
- :param conf: The configuration
- :rtype: dictionary
- :returns: The generated config
- """
- config = deepcopy(spec)
- match = re.search(r'^(\S+)', conf)
- intf = match.group(1)
-
- if get_interface_type(intf) == 'unknown':
- return {}
- # populate the facts from the configuration
- config['name'] = normalize_interface(intf)
-
- ipv4 = []
- ipv4_all = re.findall(r"ip address (\S+.*)", conf)
- for each in ipv4_all:
- each_ipv4 = dict()
- if 'secondary' not in each and 'dhcp' not in each:
- each_ipv4['address'] = each
- elif 'secondary' in each:
- each_ipv4['address'] = each.split(' secondary')[0]
- each_ipv4['secondary'] = True
- elif 'dhcp' in each:
- each_ipv4['address'] = 'dhcp'
- if 'client-id' in each:
- each_ipv4['dhcp_client'] = int(each.split(' hostname ')[0].split('/')[-1])
- if 'hostname' in each:
- each_ipv4["dhcp_hostname"] = each.split(' hostname ')[-1]
- if 'client-id' in each and each_ipv4['dhcp_client'] is None:
- each_ipv4['dhcp_client'] = int(each.split('/')[-1])
- if 'hostname' in each and not each_ipv4["dhcp_hostname"]:
- each_ipv4["dhcp_hostname"] = each.split(' hostname ')[-1]
- ipv4.append(each_ipv4)
- config['ipv4'] = ipv4
-
- # Get the configured IPV6 details
- ipv6 = []
- ipv6_all = re.findall(r"ipv6 address (\S+)", conf)
- for each in ipv6_all:
- each_ipv6 = dict()
- if 'autoconfig' in each:
- each_ipv6['autoconfig'] = True
- if 'dhcp' in each:
- each_ipv6['dhcp'] = True
- each_ipv6['address'] = each.lower()
- ipv6.append(each_ipv6)
- config['ipv6'] = ipv6
-
- return utils.remove_empties(config)
diff --git a/lib/ansible/module_utils/network/ios/facts/lacp/lacp.py b/lib/ansible/module_utils/network/ios/facts/lacp/lacp.py
deleted file mode 100644
index 455460fc94..0000000000
--- a/lib/ansible/module_utils/network/ios/facts/lacp/lacp.py
+++ /dev/null
@@ -1,83 +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 ios lacp fact class
-It is in this file the configuration is collected from the device
-for a given resource, parsed, and the facts tree is populated
-based on the configuration.
-"""
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-from copy import deepcopy
-from ansible.module_utils.network.common import utils
-from ansible.module_utils.network.ios.argspec.lacp.lacp import LacpArgs
-
-
-class LacpFacts(object):
- """ The ios lacp fact class
- """
-
- def __init__(self, module, subspec='config', options='options'):
- self._module = module
- self.argument_spec = LacpArgs.argument_spec
- spec = deepcopy(self.argument_spec)
- if subspec:
- if options:
- facts_argument_spec = spec[subspec][options]
- else:
- facts_argument_spec = spec[subspec]
- else:
- facts_argument_spec = spec
-
- self.generated_spec = utils.generate_dict(facts_argument_spec)
-
- def populate_facts(self, connection, ansible_facts, data=None):
- """ Populate the facts for lacp
- :param connection: the device connection
- :param ansible_facts: Facts dictionary
- :param data: previously collected conf
- :rtype: dictionary
- :returns: facts
- """
- if connection:
- pass
-
- if not data:
- data = connection.get('show lacp sys-id')
-
- obj = {}
- if data:
- lacp_obj = self.render_config(self.generated_spec, data)
- if lacp_obj:
- obj = lacp_obj
-
- ansible_facts['ansible_network_resources'].pop('lacp', None)
- facts = {}
-
- params = utils.validate_config(self.argument_spec, {'config': obj})
- facts['lacp'] = utils.remove_empties(params['config'])
- ansible_facts['ansible_network_resources'].update(facts)
-
- return ansible_facts
-
- def render_config(self, spec, conf):
- """
- Render config as dictionary structure and delete keys
- from spec for null values
-
- :param spec: The facts tree, generated from the argspec
- :param conf: The configuration
- :rtype: dictionary
- :returns: The generated config
- """
- config = deepcopy(spec)
-
- config['system']['priority'] = int(conf.split(',')[0])
-
- return utils.remove_empties(config)
diff --git a/lib/ansible/module_utils/network/ios/facts/lacp_interfaces/lacp_interfaces.py b/lib/ansible/module_utils/network/ios/facts/lacp_interfaces/lacp_interfaces.py
deleted file mode 100644
index 722557e269..0000000000
--- a/lib/ansible/module_utils/network/ios/facts/lacp_interfaces/lacp_interfaces.py
+++ /dev/null
@@ -1,102 +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 ios_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.ios.utils.utils import get_interface_type, normalize_interface
-from ansible.module_utils.network.ios.argspec.lacp_interfaces.lacp_interfaces import Lacp_InterfacesArgs
-
-
-class Lacp_InterfacesFacts(object):
- """ The ios_lacp_interfaces fact class
- """
-
- def __init__(self, module, subspec='config', options='options'):
-
- self._module = module
- self.argument_spec = Lacp_InterfacesArgs.argument_spec
- spec = deepcopy(self.argument_spec)
- if subspec:
- if options:
- facts_argument_spec = spec[subspec][options]
- else:
- facts_argument_spec = spec[subspec]
- else:
- facts_argument_spec = spec
-
- self.generated_spec = utils.generate_dict(facts_argument_spec)
-
- def populate_facts(self, connection, ansible_facts, data=None):
- """ Populate the facts for lacp_interfaces
- :param connection: the device connection
- :param ansible_facts: Facts dictionary
- :param data: previously collected conf
- :rtype: dictionary
- :returns: facts
- """
- if connection:
- pass
-
- objs = []
- if not data:
- data = connection.get('show running-config | section ^interface')
- # operate on a collection of resource x
- config = data.split('interface ')
-
- for conf in config:
- if conf:
- obj = self.render_config(self.generated_spec, conf)
- if obj:
- objs.append(obj)
- facts = {}
-
- if objs:
- facts['lacp_interfaces'] = []
- params = utils.validate_config(self.argument_spec, {'config': objs})
- for cfg in params['config']:
- facts['lacp_interfaces'].append(utils.remove_empties(cfg))
- ansible_facts['ansible_network_resources'].update(facts)
-
- return ansible_facts
-
- def render_config(self, spec, conf):
- """
- Render config as dictionary structure and delete keys
- from spec for null values
-
- :param spec: The facts tree, generated from the argspec
- :param conf: The configuration
- :rtype: dictionary
- :returns: The generated config
- """
- config = deepcopy(spec)
- match = re.search(r'^(\S+)', conf)
- intf = match.group(1)
- if get_interface_type(intf) == 'unknown':
- return {}
-
- config['name'] = normalize_interface(intf)
- port_priority = utils.parse_conf_arg(conf, 'lacp port-priority')
- max_bundle = utils.parse_conf_arg(conf, 'lacp max-bundle')
- if port_priority:
- config['port_priority'] = int(port_priority)
- if 'lacp fast-switchover' in conf:
- config['fast_switchover'] = True
- if max_bundle:
- config['max_bundle'] = int(max_bundle)
-
- return utils.remove_empties(config)
diff --git a/lib/ansible/module_utils/network/ios/facts/lag_interfaces/lag_interfaces.py b/lib/ansible/module_utils/network/ios/facts/lag_interfaces/lag_interfaces.py
deleted file mode 100644
index e396bb0b51..0000000000
--- a/lib/ansible/module_utils/network/ios/facts/lag_interfaces/lag_interfaces.py
+++ /dev/null
@@ -1,118 +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 ios lag_interfaces fact class
-It is in this file the configuration is collected from the device
-for a given resource, parsed, and the facts tree is populated
-based on the configuration.
-"""
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-import re
-from copy import deepcopy
-
-from ansible.module_utils.network.common import utils
-from ansible.module_utils.network.ios.utils.utils import get_interface_type, normalize_interface
-from ansible.module_utils.network.ios.argspec.lag_interfaces.lag_interfaces import Lag_interfacesArgs
-
-
-class Lag_interfacesFacts(object):
- """ The ios_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 interfaces
- :param connection: the device connection
- :param ansible_facts: Facts dictionary
- :param data: previously collected conf
- :rtype: dictionary
- :returns: facts
- """
- objs = []
-
- if not data:
- data = connection.get('show running-config | section ^interface')
- # operate on a collection of resource x
- config = data.split('interface ')
- for conf in config:
- if conf:
- obj = self.render_config(self.generated_spec, conf)
- if obj:
- if not obj.get('members'):
- obj.update({'members': []})
- objs.append(obj)
-
- # for appending members configured with same channel-group
- for each in range(len(objs)):
- if each < (len(objs) - 1):
- if objs[each]['name'] == objs[each + 1]['name']:
- objs[each]['members'].append(objs[each + 1]['members'][0])
- del objs[each + 1]
- facts = {}
-
- if objs:
- facts['lag_interfaces'] = []
- params = utils.validate_config(self.argument_spec, {'config': objs})
-
- for cfg in params['config']:
- facts['lag_interfaces'].append(utils.remove_empties(cfg))
- ansible_facts['ansible_network_resources'].update(facts)
-
- return ansible_facts
-
- def render_config(self, spec, conf):
- """
- Render config as dictionary structure and delete keys
- from spec for null values
-
- :param spec: The facts tree, generated from the argspec
- :param conf: The configuration
- :rtype: dictionary
- :returns: The generated config
- """
- config = deepcopy(spec)
- match = re.search(r'^(\S+)', conf)
- intf = match.group(1)
-
- if get_interface_type(intf) == 'unknown':
- return {}
- member_config = {}
- channel_group = utils.parse_conf_arg(conf, 'channel-group')
- if intf.startswith('Gi'):
- config['name'] = intf
- config['members'] = []
- if channel_group:
- channel_group = channel_group.split(' ')
- id = channel_group[0]
- config['name'] = 'Port-channel{0}'.format(str(id))
- if 'mode' in channel_group:
- mode = channel_group[2]
- member_config.update({'mode': mode})
- if 'link' in channel_group:
- link = channel_group[2]
- member_config.update({'link': link})
- if member_config.get('mode') or member_config.get('link'):
- member_config['member'] = normalize_interface(intf)
- config['members'].append(member_config)
-
- return utils.remove_empties(config)
diff --git a/lib/ansible/module_utils/network/ios/facts/legacy/base.py b/lib/ansible/module_utils/network/ios/facts/legacy/base.py
deleted file mode 100644
index 75a7e9974d..0000000000
--- a/lib/ansible/module_utils/network/ios/facts/legacy/base.py
+++ /dev/null
@@ -1,380 +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 ios legacy fact class
-It is in this file the configuration is collected from the device
-for a given resource, parsed, and the facts tree is populated
-based on the configuration.
-"""
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-import platform
-import re
-
-from ansible.module_utils.network.ios.ios import run_commands, get_capabilities
-from ansible.module_utils.network.ios.ios import normalize_interface
-from ansible.module_utils.six import iteritems
-from ansible.module_utils.six.moves import zip
-
-
-class FactsBase(object):
-
- COMMANDS = list()
-
- def __init__(self, module):
- self.module = module
- self.facts = dict()
- self.warnings = list()
- self.responses = None
-
- def populate(self):
- self.responses = run_commands(self.module, commands=self.COMMANDS, check_rc=False)
-
- def run(self, cmd):
- return run_commands(self.module, commands=cmd, check_rc=False)
-
-
-class Default(FactsBase):
-
- COMMANDS = ['show version']
-
- def populate(self):
- super(Default, self).populate()
- self.facts.update(self.platform_facts())
- data = self.responses[0]
- if data:
- self.facts['iostype'] = self.parse_iostype(data)
- self.facts['serialnum'] = self.parse_serialnum(data)
- self.parse_stacks(data)
-
- def parse_iostype(self, data):
- match = re.search(r'\S+(X86_64_LINUX_IOSD-UNIVERSALK9-M)(\S+)', data)
- if match:
- return "IOS-XE"
- else:
- return "IOS"
-
- def parse_serialnum(self, data):
- match = re.search(r'board ID (\S+)', data)
- if match:
- return match.group(1)
-
- def parse_stacks(self, data):
- match = re.findall(r'^Model [Nn]umber\s+: (\S+)', data, re.M)
- if match:
- self.facts['stacked_models'] = match
-
- match = re.findall(r'^System [Ss]erial [Nn]umber\s+: (\S+)', data, re.M)
- if match:
- self.facts['stacked_serialnums'] = match
-
- 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',
- 'show memory statistics'
- ]
-
- def populate(self):
- warnings = list()
- super(Hardware, self).populate()
- data = self.responses[0]
- if data:
- self.facts['filesystems'] = self.parse_filesystems(data)
- self.facts['filesystems_info'] = self.parse_filesystems_info(data)
-
- data = self.responses[1]
- if data:
- if 'Invalid input detected' in data:
- warnings.append('Unable to gather memory statistics')
- else:
- processor_line = [l for l in data.splitlines()
- if 'Processor' in l].pop()
- match = re.findall(r'\s(\d+)\s', processor_line)
- if match:
- self.facts['memtotal_mb'] = int(match[0]) / 1024
- self.facts['memfree_mb'] = int(match[3]) / 1024
-
- def parse_filesystems(self, data):
- return re.findall(r'^Directory of (\S+)/', data, re.M)
-
- def parse_filesystems_info(self, data):
- facts = dict()
- fs = ''
- for line in data.split('\n'):
- match = re.match(r'^Directory of (\S+)/', line)
- if match:
- fs = match.group(1)
- facts[fs] = dict()
- continue
- match = re.match(r'^(\d+) bytes total \((\d+) bytes free\)', line)
- if match:
- facts[fs]['spacetotal_kb'] = int(match.group(1)) / 1024
- facts[fs]['spacefree_kb'] = int(match.group(2)) / 1024
- return facts
-
-
-class Config(FactsBase):
-
- COMMANDS = ['show running-config']
-
- def populate(self):
- super(Config, self).populate()
- data = self.responses[0]
- if data:
- data = re.sub(
- r'^Building configuration...\s+Current configuration : \d+ bytes\n',
- '', data, flags=re.MULTILINE)
- self.facts['config'] = data
-
-
-class Interfaces(FactsBase):
-
- COMMANDS = [
- 'show interfaces',
- 'show ip interface',
- 'show ipv6 interface',
- 'show lldp',
- 'show cdp'
- ]
-
- def populate(self):
- super(Interfaces, self).populate()
-
- self.facts['all_ipv4_addresses'] = list()
- self.facts['all_ipv6_addresses'] = list()
- self.facts['neighbors'] = {}
-
- data = self.responses[0]
- if data:
- interfaces = self.parse_interfaces(data)
- self.facts['interfaces'] = self.populate_interfaces(interfaces)
-
- data = self.responses[1]
- if data:
- data = self.parse_interfaces(data)
- self.populate_ipv4_interfaces(data)
-
- data = self.responses[2]
- if data:
- data = self.parse_interfaces(data)
- self.populate_ipv6_interfaces(data)
-
- data = self.responses[3]
- lldp_errs = ['Invalid input', 'LLDP is not enabled']
-
- if data and not any(err in data for err in lldp_errs):
- neighbors = self.run(['show lldp neighbors detail'])
- if neighbors:
- self.facts['neighbors'].update(self.parse_neighbors(neighbors[0]))
-
- data = self.responses[4]
- cdp_errs = ['CDP is not enabled']
-
- if data and not any(err in data for err in cdp_errs):
- cdp_neighbors = self.run(['show cdp neighbors detail'])
- if cdp_neighbors:
- self.facts['neighbors'].update(self.parse_cdp_neighbors(cdp_neighbors[0]))
-
- def populate_interfaces(self, interfaces):
- facts = dict()
- for key, value in iteritems(interfaces):
- intf = dict()
- intf['description'] = self.parse_description(value)
- intf['macaddress'] = self.parse_macaddress(value)
-
- intf['mtu'] = self.parse_mtu(value)
- intf['bandwidth'] = self.parse_bandwidth(value)
- intf['mediatype'] = self.parse_mediatype(value)
- intf['duplex'] = self.parse_duplex(value)
- intf['lineprotocol'] = self.parse_lineprotocol(value)
- intf['operstatus'] = self.parse_operstatus(value)
- intf['type'] = self.parse_type(value)
-
- facts[key] = intf
- return facts
-
- def populate_ipv4_interfaces(self, data):
- for key, value in data.items():
- self.facts['interfaces'][key]['ipv4'] = list()
- primary_address = addresses = []
- primary_address = re.findall(r'Internet address is (.+)$', value, re.M)
- addresses = re.findall(r'Secondary address (.+)$', value, re.M)
- if len(primary_address) == 0:
- continue
- addresses.append(primary_address[0])
- for address in addresses:
- addr, subnet = address.split("/")
- ipv4 = dict(address=addr.strip(), subnet=subnet.strip())
- self.add_ip_address(addr.strip(), 'ipv4')
- self.facts['interfaces'][key]['ipv4'].append(ipv4)
-
- def populate_ipv6_interfaces(self, data):
- for key, value in iteritems(data):
- try:
- self.facts['interfaces'][key]['ipv6'] = list()
- except KeyError:
- self.facts['interfaces'][key] = dict()
- self.facts['interfaces'][key]['ipv6'] = list()
- addresses = re.findall(r'\s+(.+), subnet', value, re.M)
- subnets = re.findall(r', subnet is (.+)$', value, re.M)
- for addr, subnet in zip(addresses, subnets):
- ipv6 = dict(address=addr.strip(), subnet=subnet.strip())
- self.add_ip_address(addr.strip(), 'ipv6')
- self.facts['interfaces'][key]['ipv6'].append(ipv6)
-
- def add_ip_address(self, address, family):
- if family == 'ipv4':
- self.facts['all_ipv4_addresses'].append(address)
- else:
- self.facts['all_ipv6_addresses'].append(address)
-
- def parse_neighbors(self, neighbors):
- facts = dict()
- for entry in neighbors.split('------------------------------------------------'):
- if entry == '':
- continue
- intf = self.parse_lldp_intf(entry)
- if intf is None:
- return facts
- intf = normalize_interface(intf)
- if intf not in facts:
- facts[intf] = list()
- fact = dict()
- fact['host'] = self.parse_lldp_host(entry)
- fact['port'] = self.parse_lldp_port(entry)
- facts[intf].append(fact)
- return facts
-
- def parse_cdp_neighbors(self, neighbors):
- facts = dict()
- for entry in neighbors.split('-------------------------'):
- if entry == '':
- continue
- intf_port = self.parse_cdp_intf_port(entry)
- if intf_port is None:
- return facts
- intf, port = intf_port
- if intf not in facts:
- facts[intf] = list()
- fact = dict()
- fact['host'] = self.parse_cdp_host(entry)
- fact['port'] = port
- facts[intf].append(fact)
- return facts
-
- def parse_interfaces(self, data):
- parsed = dict()
- key = ''
- for line in data.split('\n'):
- if len(line) == 0:
- continue
- elif line[0] == ' ':
- parsed[key] += '\n%s' % line
- else:
- match = re.match(r'^(\S+)', line)
- if match:
- key = match.group(1)
- parsed[key] = line
- return parsed
-
- def parse_description(self, data):
- match = re.search(r'Description: (.+)$', data, re.M)
- if match:
- return match.group(1)
-
- def parse_macaddress(self, data):
- match = re.search(r'Hardware is (?:.*), address is (\S+)', data)
- if match:
- return match.group(1)
-
- def parse_ipv4(self, data):
- match = re.search(r'Internet address is (\S+)', data)
- if match:
- addr, masklen = match.group(1).split('/')
- return dict(address=addr, masklen=int(masklen))
-
- def parse_mtu(self, data):
- match = re.search(r'MTU (\d+)', data)
- if match:
- return int(match.group(1))
-
- def parse_bandwidth(self, data):
- match = re.search(r'BW (\d+)', data)
- if match:
- return int(match.group(1))
-
- def parse_duplex(self, data):
- match = re.search(r'(\w+) Duplex', data, re.M)
- if match:
- return match.group(1)
-
- def parse_mediatype(self, data):
- match = re.search(r'media type is (.+)$', data, re.M)
- if match:
- return match.group(1)
-
- def parse_type(self, data):
- match = re.search(r'Hardware is (.+),', data, re.M)
- if match:
- return match.group(1)
-
- def parse_lineprotocol(self, data):
- match = re.search(r'line protocol is (\S+)\s*$', data, re.M)
- if match:
- return match.group(1)
-
- def parse_operstatus(self, data):
- match = re.search(r'^(?:.+) is (.+),', data, re.M)
- if match:
- return match.group(1)
-
- def parse_lldp_intf(self, data):
- match = re.search(r'^Local Intf: (.+)$', data, re.M)
- if match:
- return match.group(1)
-
- def parse_lldp_host(self, data):
- match = re.search(r'System Name: (.+)$', data, re.M)
- if match:
- return match.group(1)
-
- def parse_lldp_port(self, data):
- match = re.search(r'Port id: (.+)$', data, re.M)
- if match:
- return match.group(1)
-
- def parse_cdp_intf_port(self, data):
- match = re.search(r'^Interface: (.+), Port ID \(outgoing port\): (.+)$', data, re.M)
- if match:
- return match.group(1), match.group(2)
-
- def parse_cdp_host(self, data):
- match = re.search(r'^Device ID: (.+)$', data, re.M)
- if match:
- return match.group(1)
diff --git a/lib/ansible/module_utils/network/ios/facts/lldp_global/lldp_global.py b/lib/ansible/module_utils/network/ios/facts/lldp_global/lldp_global.py
deleted file mode 100644
index 1643d52476..0000000000
--- a/lib/ansible/module_utils/network/ios/facts/lldp_global/lldp_global.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 ios 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
-
-
-from copy import deepcopy
-from ansible.module_utils.network.common import utils
-from ansible.module_utils.network.ios.argspec.lldp_global.lldp_global import Lldp_globalArgs
-
-
-class Lldp_globalFacts(object):
- """ The ios 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
- """
- objs = dict()
- if not data:
- data = connection.get('show running-config | section ^lldp')
- # operate on a collection of resource x
- config = data.split('\n')
- for conf in config:
- if conf:
- obj = self.render_config(self.generated_spec, conf)
- if obj:
- objs.update(obj)
- facts = {}
-
- if objs:
- params = utils.validate_config(self.argument_spec, {'config': utils.remove_empties(objs)})
- facts['lldp_global'] = utils.remove_empties(params['config'])
- ansible_facts['ansible_network_resources'].update(facts)
-
- return ansible_facts
-
- def render_config(self, spec, conf):
- """
- Render config as dictionary structure and delete keys from spec for null values
-
- :param spec: The facts tree, generated from the argspec
- :param conf: The configuration
- :rtype: dictionary
- :returns: The generated config
- """
- config = deepcopy(spec)
-
- holdtime = utils.parse_conf_arg(conf, 'lldp holdtime')
- timer = utils.parse_conf_arg(conf, 'lldp timer')
- reinit = utils.parse_conf_arg(conf, 'lldp reinit')
- if holdtime:
- config['holdtime'] = int(holdtime)
- if 'lldp run' in conf:
- config['enabled'] = True
- if timer:
- config['timer'] = int(timer)
- if reinit:
- config['reinit'] = int(reinit)
-
- return utils.remove_empties(config)
diff --git a/lib/ansible/module_utils/network/ios/facts/lldp_interfaces/lldp_interfaces.py b/lib/ansible/module_utils/network/ios/facts/lldp_interfaces/lldp_interfaces.py
deleted file mode 100644
index f97f87fbc4..0000000000
--- a/lib/ansible/module_utils/network/ios/facts/lldp_interfaces/lldp_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 ios_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.ios.utils.utils import get_interface_type, normalize_interface
-from ansible.module_utils.network.ios.argspec.lldp_interfaces.lldp_interfaces import Lldp_InterfacesArgs
-
-
-class Lldp_InterfacesFacts(object):
- """ The ios_lldp_interfaces fact class
- """
-
- def __init__(self, module, subspec='config', options='options'):
-
- self._module = module
- self.argument_spec = Lldp_InterfacesArgs.argument_spec
- spec = deepcopy(self.argument_spec)
- if subspec:
- if options:
- facts_argument_spec = spec[subspec][options]
- else:
- facts_argument_spec = spec[subspec]
- else:
- facts_argument_spec = spec
-
- self.generated_spec = utils.generate_dict(facts_argument_spec)
-
- def populate_facts(self, connection, ansible_facts, data=None):
- """ Populate the facts for lldp_interfaces
- :param connection: the device connection
- :param ansible_facts: Facts dictionary
- :param data: previously collected conf
- :rtype: dictionary
- :returns: facts
- """
- if connection:
- pass
-
- objs = []
- if not data:
- data = connection.get('show lldp interface')
- # operate on a collection of resource x
- config = data.split('\n\n')
-
- for conf in config:
- if conf:
- obj = self.render_config(self.generated_spec, conf)
- if obj:
- objs.append(obj)
- facts = {}
-
- if objs:
- facts['lldp_interfaces'] = []
- params = utils.validate_config(self.argument_spec, {'config': objs})
- for cfg in params['config']:
- facts['lldp_interfaces'].append(utils.remove_empties(cfg))
- ansible_facts['ansible_network_resources'].update(facts)
-
- return ansible_facts
-
- def render_config(self, spec, conf):
- """
- Render config as dictionary structure and delete keys
- from spec for null values
-
- :param spec: The facts tree, generated from the argspec
- :param conf: The configuration
- :rtype: dictionary
- :returns: The generated config
- """
- config = deepcopy(spec)
- match = re.search(r'^(\S+)(:)', conf)
- intf = ''
- if match:
- intf = match.group(1)
-
- if get_interface_type(intf) == 'unknown':
- return {}
- if intf.lower().startswith('gi'):
- config['name'] = normalize_interface(intf)
- receive = utils.parse_conf_arg(conf, 'Rx:')
- transmit = utils.parse_conf_arg(conf, 'Tx:')
-
- if receive == 'enabled':
- config['receive'] = True
- elif receive == 'disabled':
- config['receive'] = False
- if transmit == 'enabled':
- config['transmit'] = True
- elif transmit == 'disabled':
- config['transmit'] = False
-
- return utils.remove_empties(config)
diff --git a/lib/ansible/module_utils/network/ios/facts/static_routes/static_routes.py b/lib/ansible/module_utils/network/ios/facts/static_routes/static_routes.py
deleted file mode 100644
index f7ada0b3f5..0000000000
--- a/lib/ansible/module_utils/network/ios/facts/static_routes/static_routes.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 ios_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
-
-
-from copy import deepcopy
-from ansible.module_utils.network.common import utils
-from ansible.module_utils.network.ios.utils.utils import netmask_to_cidr
-from ansible.module_utils.network.ios.argspec.static_routes.static_routes import Static_RoutesArgs
-
-
-class Static_RoutesFacts(object):
- """ The ios_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_static_routes_data(self, connection):
- return connection.get('sh running-config | include ip route|ipv6 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
- """
-
- objs = []
- if not data:
- data = self.get_static_routes_data(connection)
- # operate on a collection of resource x
- config = data.split('\n')
-
- same_dest = self.populate_destination(config)
- for key in same_dest.keys():
- if key:
- obj = self.render_config(self.generated_spec, key, same_dest[key])
- if obj:
- objs.append(obj)
- facts = {}
-
- # append all static routes address_family with NO VRF together
- no_vrf_address_family = {
- 'address_families': [each.get('address_families')[0] for each in objs if each.get('vrf') is None]
- }
-
- temp_objs = [each for each in objs if each.get('vrf') is not None]
- temp_objs.append(no_vrf_address_family)
- objs = temp_objs
-
- 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 update_netmask_to_cidr(self, filter, pos, del_pos):
- netmask = filter.split(' ')
- dest = netmask[pos] + '/' + netmask_to_cidr(netmask[del_pos])
- netmask[pos] = dest
- del netmask[del_pos]
- filter_vrf = ' '
- return filter_vrf.join(netmask), dest
-
- def populate_destination(self, config):
- same_dest = {}
- ip_str = ''
- for i in sorted(config):
- if i:
- if '::' in i and 'vrf' in i:
- ip_str = 'ipv6 route vrf'
- elif '::' in i and 'vrf' not in i:
- ip_str = 'ipv6 route'
- elif '.' in i and 'vrf' in i:
- ip_str = 'ip route vrf'
- elif '.' in i and 'vrf' not in i:
- ip_str = 'ip route'
-
- if 'vrf' in i:
- filter_vrf = utils.parse_conf_arg(i, ip_str)
- if '/' not in filter_vrf and '::' not in filter_vrf:
- filter_vrf, dest_vrf = self.update_netmask_to_cidr(filter_vrf, 1, 2)
- dest_vrf = dest_vrf + '_vrf'
- else:
- dest_vrf = filter_vrf.split(' ')[1]
- if dest_vrf not in same_dest.keys():
- same_dest[dest_vrf] = []
- same_dest[dest_vrf].append('vrf ' + filter_vrf)
- elif 'vrf' not in same_dest[dest_vrf][0]:
- same_dest[dest_vrf] = []
- same_dest[dest_vrf].append('vrf ' + filter_vrf)
- else:
- same_dest[dest_vrf].append(('vrf ' + filter_vrf))
- else:
- filter = utils.parse_conf_arg(i, ip_str)
- if '/' not in filter and '::' not in filter:
- filter, dest = self.update_netmask_to_cidr(filter, 0, 1)
- else:
- dest = filter.split(' ')[0]
- if dest not in same_dest.keys():
- same_dest[dest] = []
- same_dest[dest].append(filter)
- elif 'vrf' in same_dest[dest][0]:
- same_dest[dest] = []
- same_dest[dest].append(filter)
- else:
- same_dest[dest].append(filter)
- return same_dest
-
- def render_config(self, spec, conf, conf_val):
- """
- 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['address_families'] = []
- route_dict = dict()
- final_route = dict()
- afi = dict()
- final_route['routes'] = []
- next_hops = []
- hops = {}
- vrf = ''
- address_family = dict()
- for each in conf_val:
- route = each.split(' ')
- if 'vrf' in conf_val[0]:
- vrf = route[route.index('vrf') + 1]
- route_dict['dest'] = conf.split('_')[0]
- else:
- route_dict['dest'] = conf
- if 'vrf' in conf_val[0]:
- hops = {}
- if '::' in conf:
- hops['forward_router_address'] = route[3]
- afi['afi'] = 'ipv6'
- elif '.' in conf:
- hops['forward_router_address'] = route[3]
- afi['afi'] = "ipv4"
- else:
- hops['interface'] = conf
- else:
-
- if '::' in conf:
- hops['forward_router_address'] = route[1]
- afi['afi'] = 'ipv6'
- elif '.' in conf:
- hops['forward_router_address'] = route[1]
- afi['afi'] = "ipv4"
- else:
- hops['interface'] = route[1]
- try:
- temp_list = each.split(' ')
- if 'tag' in temp_list:
- del temp_list[temp_list.index('tag') + 1]
- if 'track' in temp_list:
- del temp_list[temp_list.index('track') + 1]
- # find distance metric
- dist_metrics = int(
- [i for i in temp_list if '.' not in i and ':' not in i and ord(i[0]) > 48 and ord(i[0]) < 57][0]
- )
- except IndexError:
- dist_metrics = None
- if dist_metrics:
- hops['distance_metric'] = dist_metrics
- if 'name' in route:
- hops['name'] = route[route.index('name') + 1]
- if 'multicast' in route:
- hops['multicast'] = True
- if 'dhcp' in route:
- hops['dhcp'] = True
- if 'global' in route:
- hops['global'] = True
- if 'permanent' in route:
- hops['permanent'] = True
- if 'tag' in route:
- hops['tag'] = route[route.index('tag') + 1]
- if 'track' in route:
- hops['track'] = route[route.index('track') + 1]
- next_hops.append(hops)
- hops = {}
- route_dict['next_hops'] = next_hops
- if route_dict:
- final_route['routes'].append(route_dict)
- address_family.update(afi)
- address_family.update(final_route)
- config['address_families'].append(address_family)
- if vrf:
- config['vrf'] = vrf
-
- return utils.remove_empties(config)
diff --git a/lib/ansible/module_utils/network/ios/facts/vlans/vlans.py b/lib/ansible/module_utils/network/ios/facts/vlans/vlans.py
deleted file mode 100644
index b499be5ce9..0000000000
--- a/lib/ansible/module_utils/network/ios/facts/vlans/vlans.py
+++ /dev/null
@@ -1,144 +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 ios 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
-from ansible.module_utils.network.common import utils
-from ansible.module_utils.network.ios.argspec.vlans.vlans import VlansArgs
-
-
-class VlansFacts(object):
- """ The ios 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 connection:
- pass
-
- objs = []
- mtu_objs = []
- remote_objs = []
- final_objs = []
- if not data:
- data = connection.get('show vlan')
- # operate on a collection of resource x
- config = data.split('\n')
- # Get individual vlan configs separately
- vlan_info = ''
- for conf in config:
- if 'Name' in conf:
- vlan_info = 'Name'
- elif 'Type' in conf:
- vlan_info = 'Type'
- elif 'Remote' in conf:
- vlan_info = 'Remote'
- if conf and ' ' not in filter(None, conf.split('-')):
- obj = self.render_config(self.generated_spec, conf, vlan_info)
- if 'mtu' in obj:
- mtu_objs.append(obj)
- elif 'remote_span' in obj:
- remote_objs = obj
- elif obj:
- objs.append(obj)
- # Appending MTU value to the retrieved dictionary
- for o, m in zip(objs, mtu_objs):
- o.update(m)
- final_objs.append(o)
-
- # Appending Remote Span value to related VLAN:
- if remote_objs:
- if remote_objs.get('remote_span'):
- for each in remote_objs.get('remote_span'):
- for every in final_objs:
- if each == every.get('vlan_id'):
- every.update({'remote_span': True})
- break
-
- facts = {}
- if final_objs:
- facts['vlans'] = []
- params = utils.validate_config(self.argument_spec, {'config': objs})
-
- for cfg in params['config']:
- facts['vlans'].append(utils.remove_empties(cfg))
- ansible_facts['ansible_network_resources'].update(facts)
-
- return ansible_facts
-
- def render_config(self, spec, conf, vlan_info):
- """
- 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)
-
- if vlan_info == 'Name' and 'Name' not in conf:
- conf = list(filter(None, conf.split(' ')))
- config['vlan_id'] = int(conf[0])
- config['name'] = conf[1]
- if len(conf[2].split('/')) > 1:
- if conf[2].split('/')[0] == 'sus':
- config['state'] = 'suspend'
- elif conf[2].split('/')[0] == 'act':
- config['state'] = 'active'
- config['shutdown'] = 'enabled'
- else:
- if conf[2] == 'suspended':
- config['state'] = 'suspend'
- elif conf[2] == 'active':
- config['state'] = 'active'
- config['shutdown'] = 'disabled'
- elif vlan_info == 'Type' and 'Type' not in conf:
- conf = list(filter(None, conf.split(' ')))
- config['mtu'] = int(conf[3])
- elif vlan_info == 'Remote':
- if len(conf.split(',')) > 1 or conf.isdigit():
- remote_span_vlan = []
- if len(conf.split(',')) > 1:
- remote_span_vlan = conf.split(',')
- else:
- remote_span_vlan.append(conf)
- remote_span = []
- for each in remote_span_vlan:
- remote_span.append(int(each))
- config['remote_span'] = remote_span
-
- return utils.remove_empties(config)
diff --git a/lib/ansible/module_utils/network/ios/ios.py b/lib/ansible/module_utils/network/ios/ios.py
deleted file mode 100644
index 3e1c680aa3..0000000000
--- a/lib/ansible/module_utils/network/ios/ios.py
+++ /dev/null
@@ -1,183 +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) 2016 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
-
-from ansible.module_utils._text import to_text
-from ansible.module_utils.basic import env_fallback
-from ansible.module_utils.network.common.utils import to_list
-from ansible.module_utils.connection import Connection, ConnectionError
-
-_DEVICE_CONFIGS = {}
-
-ios_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(fallback=(env_fallback, ['ANSIBLE_NET_AUTH_PASS']), no_log=True),
- 'timeout': dict(type='int')
-}
-ios_argument_spec = {
- 'provider': dict(type='dict', options=ios_provider_spec, removed_in_version=2.14),
-}
-
-
-def get_provider_argspec():
- return ios_provider_spec
-
-
-def get_connection(module):
- if hasattr(module, '_ios_connection'):
- return module._ios_connection
-
- capabilities = get_capabilities(module)
- network_api = capabilities.get('network_api')
- if network_api == 'cliconf':
- module._ios_connection = Connection(module._socket_path)
- else:
- module.fail_json(msg='Invalid connection type %s' % network_api)
-
- return module._ios_connection
-
-
-def get_capabilities(module):
- if hasattr(module, '_ios_capabilities'):
- return module._ios_capabilities
- try:
- capabilities = Connection(module._socket_path).get_capabilities()
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
- module._ios_capabilities = json.loads(capabilities)
- return module._ios_capabilities
-
-
-def get_defaults_flag(module):
- connection = get_connection(module)
- try:
- out = connection.get_defaults_flag()
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
- return to_text(out, errors='surrogate_then_replace').strip()
-
-
-def get_config(module, flags=None):
- flags = to_list(flags)
-
- section_filter = False
- if flags and 'section' in flags[-1]:
- section_filter = True
-
- flag_str = ' '.join(flags)
-
- try:
- return _DEVICE_CONFIGS[flag_str]
- except KeyError:
- connection = get_connection(module)
- try:
- out = connection.get_config(flags=flags)
- except ConnectionError as exc:
- if section_filter:
- # Some ios devices don't understand `| section foo`
- out = get_config(module, flags=flags[:-1])
- else:
- module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
- cfg = to_text(out, errors='surrogate_then_replace').strip()
- _DEVICE_CONFIGS[flag_str] = cfg
- return cfg
-
-
-def run_commands(module, commands, check_rc=True):
- connection = get_connection(module)
- try:
- return connection.run_commands(commands=commands, check_rc=check_rc)
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc))
-
-
-def load_config(module, commands):
- connection = get_connection(module)
-
- try:
- resp = connection.edit_config(commands)
- return resp.get('response')
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc))
-
-
-def normalize_interface(name):
- """Return the normalized interface name
- """
- if not name:
- return
-
- def _get_number(name):
- digits = ''
- for char in name:
- if char.isdigit() or char in '/.':
- digits += char
- return digits
-
- if name.lower().startswith('gi'):
- if_type = 'GigabitEthernet'
- elif name.lower().startswith('te'):
- if_type = 'TenGigabitEthernet'
- elif name.lower().startswith('fa'):
- if_type = 'FastEthernet'
- elif name.lower().startswith('fo'):
- if_type = 'FortyGigabitEthernet'
- elif name.lower().startswith('et'):
- if_type = 'Ethernet'
- elif name.lower().startswith('vl'):
- if_type = 'Vlan'
- elif name.lower().startswith('lo'):
- if_type = 'loopback'
- elif name.lower().startswith('po'):
- if_type = 'port-channel'
- elif name.lower().startswith('nv'):
- if_type = 'nve'
- elif name.lower().startswith('twe'):
- if_type = 'TwentyFiveGigE'
- elif name.lower().startswith('hu'):
- if_type = 'HundredGigE'
- else:
- if_type = None
-
- number_list = name.split(' ')
- if len(number_list) == 2:
- if_number = number_list[-1].strip()
- else:
- if_number = _get_number(name)
-
- if if_type:
- proper_interface = if_type + if_number
- else:
- proper_interface = name
-
- return proper_interface
diff --git a/lib/ansible/module_utils/network/ios/providers/cli/config/base.py b/lib/ansible/module_utils/network/ios/providers/cli/config/base.py
deleted file mode 100644
index eade249a09..0000000000
--- a/lib/ansible/module_utils/network/ios/providers/cli/config/base.py
+++ /dev/null
@@ -1,77 +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.six import iteritems
-from ansible.module_utils.network.common.utils import to_list
-from ansible.module_utils.network.common.config import NetworkConfig
-
-
-class ConfigBase(object):
-
- argument_spec = {}
-
- mutually_exclusive = []
-
- identifier = ()
-
- def __init__(self, **kwargs):
- self.values = {}
- self._rendered_configuration = {}
- self.active_configuration = None
-
- for item in self.identifier:
- self.values[item] = kwargs.pop(item)
-
- for key, value in iteritems(kwargs):
- if key in self.argument_spec:
- setattr(self, key, value)
-
- for key, value in iteritems(self.argument_spec):
- if value.get('default'):
- if not getattr(self, key, None):
- setattr(self, key, value.get('default'))
-
- def __getattr__(self, key):
- if key in self.argument_spec:
- return self.values.get(key)
-
- def __setattr__(self, key, value):
- if key in self.argument_spec:
- if key in self.identifier:
- raise TypeError('cannot set value')
- elif value is not None:
- self.values[key] = value
- else:
- super(ConfigBase, self).__setattr__(key, value)
-
- def context_config(self, cmd):
- if 'context' not in self._rendered_configuration:
- self._rendered_configuration['context'] = list()
- self._rendered_configuration['context'].extend(to_list(cmd))
-
- def global_config(self, cmd):
- if 'global' not in self._rendered_configuration:
- self._rendered_configuration['global'] = list()
- self._rendered_configuration['global'].extend(to_list(cmd))
-
- def get_rendered_configuration(self):
- config = list()
- for section in ('context', 'global'):
- config.extend(self._rendered_configuration.get(section, []))
- return config
-
- def set_active_configuration(self, config):
- self.active_configuration = config
-
- def render(self, config=None):
- raise NotImplementedError
-
- def get_section(self, config, section):
- if config is not None:
- netcfg = NetworkConfig(indent=1, contents=config)
- try:
- config = netcfg.get_block_config(to_list(section))
- except ValueError:
- config = None
- return config
diff --git a/lib/ansible/module_utils/network/ios/providers/cli/config/bgp/address_family.py b/lib/ansible/module_utils/network/ios/providers/cli/config/bgp/address_family.py
deleted file mode 100644
index 366f6413c1..0000000000
--- a/lib/ansible/module_utils/network/ios/providers/cli/config/bgp/address_family.py
+++ /dev/null
@@ -1,140 +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.ios.providers.providers import CliProvider
-from ansible.module_utils.network.ios.providers.cli.config.bgp.neighbors import AFNeighbors
-from ansible.module_utils.common.network import to_netmask
-
-
-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']
- if item['safi'] != 'unicast':
- context += ' %s' % item['safi']
- context_commands = list()
-
- if config:
- context_path = [router_context, context]
- context_config = self.get_config_context(config, context_path, indent=1)
-
- for key, value in iteritems(item):
- if value is not None:
- meth = getattr(self, '_render_%s' % key, None)
- if meth:
- resp = meth(item, context_config)
- if resp:
- context_commands.extend(to_list(resp))
-
- if context_commands:
- commands.append(context)
- commands.extend(context_commands)
- commands.append('exit-address-family')
-
- 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']
- cmd = 'network %s' % network
- if entry['masklen']:
- cmd += ' mask %s' % to_netmask(entry['masklen'])
- network += ' mask %s' % to_netmask(entry['masklen'])
- if entry['route_map']:
- cmd += ' route-map %s' % entry['route_map']
- network += ' route-map %s' % entry['route_map']
-
- safe_list.append(network)
-
- if not config or cmd not in config:
- commands.append(cmd)
-
- if self.params['operation'] == 'replace':
- if config:
- matches = re.findall(r'network (.*)', config, re.M)
- for entry in set(matches).difference(safe_list):
- commands.append('no network %s' % entry)
-
- return commands
-
- def _render_redistribute(self, item, config=None):
- commands = list()
- safe_list = list()
-
- for entry in item['redistribute']:
- option = entry['protocol']
-
- cmd = 'redistribute %s' % entry['protocol']
-
- if entry['id'] and entry['protocol'] in ('ospf', 'ospfv3', 'eigrp'):
- cmd += ' %s' % entry['id']
- option += ' %s' % entry['id']
-
- if entry['metric']:
- cmd += ' metric %s' % entry['metric']
-
- 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/ios/providers/cli/config/bgp/neighbors.py b/lib/ansible/module_utils/network/ios/providers/cli/config/bgp/neighbors.py
deleted file mode 100644
index 2cee73382a..0000000000
--- a/lib/ansible/module_utils/network/ios/providers/cli/config/bgp/neighbors.py
+++ /dev/null
@@ -1,196 +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.ios.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_local_as(self, item, config=None):
- cmd = 'neighbor %s local-as %s' % (item['neighbor'], item['local_as'])
- if not config or cmd not in config:
- return cmd
-
- def _render_port(self, item, config=None):
- cmd = 'neighbor %s port %s' % (item['neighbor'], item['port'])
- if not config or cmd not in config:
- return cmd
-
- 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_timers(self, item, config):
- """generate bgp timer related configuration
- """
- keepalive = item['timers']['keepalive']
- holdtime = item['timers']['holdtime']
- min_neighbor_holdtime = item['timers']['min_neighbor_holdtime']
- neighbor = item['neighbor']
-
- if keepalive and holdtime:
- cmd = 'neighbor %s timers %s %s' % (neighbor, keepalive, holdtime)
- if min_neighbor_holdtime:
- cmd += ' %s' % min_neighbor_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_advertisement_interval(self, item, config=None):
- cmd = 'neighbor %s advertisement-interval %s' % (item['neighbor'], item['advertisement_interval'])
- 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_route_server_client(self, item, config=None):
- cmd = 'neighbor %s route-server-client' % item['neighbor']
- if item['route_server_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_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_next_hop_self(self, item, config=None):
- cmd = 'neighbor %s next-hop-self' % item['neighbor']
- if item['next_hop_self'] 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_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_maximum_prefix(self, item, config=None):
- cmd = 'neighbor %s maximum-prefix %s' % (item['neighbor'], item['maximum_prefix'])
- if not config or cmd not in config:
- return cmd
-
- def _render_prefix_list_in(self, item, config=None):
- cmd = 'neighbor %s prefix-list %s in' % (item['neighbor'], item['prefix_list_in'])
- if not config or cmd not in config:
- return cmd
-
- def _render_prefix_list_out(self, item, config=None):
- cmd = 'neighbor %s prefix-list %s out' % (item['neighbor'], item['prefix_list_out'])
- if not config or cmd not in config:
- return cmd
diff --git a/lib/ansible/module_utils/network/ios/providers/cli/config/bgp/process.py b/lib/ansible/module_utils/network/ios/providers/cli/config/bgp/process.py
deleted file mode 100644
index d74cf92773..0000000000
--- a/lib/ansible/module_utils/network/ios/providers/cli/config/bgp/process.py
+++ /dev/null
@@ -1,140 +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.ios.providers.providers import register_provider
-from ansible.module_utils.network.ios.providers.providers import CliProvider
-from ansible.module_utils.network.ios.providers.cli.config.bgp.neighbors import Neighbors
-from ansible.module_utils.network.ios.providers.cli.config.bgp.address_family import AddressFamily
-from ansible.module_utils.common.network import to_netmask
-
-REDISTRIBUTE_PROTOCOLS = frozenset(['ospf', 'ospfv3', 'eigrp', 'isis', 'static', 'connected',
- 'odr', 'lisp', 'mobile', 'rip'])
-
-
-@register_provider('ios', 'ios_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 = 'bgp router-id %s' % self.get_value('config.router_id')
- if not config or cmd not in config:
- return cmd
-
- def _render_log_neighbor_changes(self, config=None):
- cmd = 'bgp log-neighbor-changes'
- log_neighbor_changes = self.get_value('config.log_neighbor_changes')
- if log_neighbor_changes is True:
- if not config or cmd not in config:
- return 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']
- cmd = 'network %s' % network
- if entry['masklen'] and entry['masklen'] not in (24, 16, 8):
- cmd += ' mask %s' % to_netmask(entry['masklen'])
- network += ' mask %s' % to_netmask(entry['masklen'])
-
- if entry['route_map']:
- cmd += ' route-map %s' % entry['route_map']
- network += ' route-map %s' % entry['route_map']
-
- safe_list.append(network)
-
- if not config or cmd not in config:
- commands.append(cmd)
-
- if self.params['operation'] == 'replace':
- if config:
- matches = re.findall(r'network (.*)', config, re.M)
- for entry in set(matches).difference(safe_list):
- commands.append('no network %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=None):
- 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':
- if address_family and root_networks:
- for item in address_family:
- if item['networks']:
- raise ValueError('operation is replace but provided both root level network(s) and network(s) under %s %s address family'
- % (item['afi'], item['safi']))
-
- if root_networks and 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/ios/providers/module.py b/lib/ansible/module_utils/network/ios/providers/module.py
deleted file mode 100644
index 69c6dd9659..0000000000
--- a/lib/ansible/module_utils/network/ios/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.ios.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/ios/providers/providers.py b/lib/ansible/module_utils/network/ios/providers/providers.py
deleted file mode 100644
index a466b033d9..0000000000
--- a/lib/ansible/module_utils/network/ios/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=1):
- if config is not None:
- netcfg = NetworkConfig(indent=indent, contents=config)
- try:
- config = netcfg.get_block_config(to_list(path))
- except ValueError:
- config = None
- return config
-
- def render(self, config=None):
- raise NotImplementedError(self.__class__.__name__)
-
- def cli(self, command):
- try:
- if not hasattr(self, '_command_output'):
- setattr(self, '_command_output', {})
- return self._command_output[command]
- except KeyError:
- out = self.connection.get(command)
- try:
- out = json.loads(out)
- except ValueError:
- pass
- self._command_output[command] = out
- return out
-
- def get_facts(self, subset=None):
- return self.populate()
-
- def edit_config(self, config=None):
- commands = self.render(config)
- if commands and self.check_mode is False:
- self.connection.edit_config(commands)
- return commands
diff --git a/lib/ansible/module_utils/network/ios/utils/utils.py b/lib/ansible/module_utils/network/ios/utils/utils.py
deleted file mode 100644
index cfcfe82dbc..0000000000
--- a/lib/ansible/module_utils/network/ios/utils/utils.py
+++ /dev/null
@@ -1,328 +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
-
-import socket
-from ansible.module_utils.six import iteritems
-from ansible.module_utils.network.common.utils import is_masklen, to_netmask
-
-
-def remove_command_from_config_list(interface, cmd, commands):
- # To delete the passed config
- if interface not in commands:
- commands.insert(0, interface)
- commands.append('no %s' % cmd)
- return commands
-
-
-def add_command_to_config_list(interface, cmd, commands):
- # To set the passed config
- if interface not in commands:
- commands.insert(0, interface)
- commands.append(cmd)
-
-
-def check_n_return_valid_ipv6_addr(module, input_list, filtered_ipv6_list):
- # To verify the valid ipv6 address
- try:
- for each in input_list:
- if '::' in each:
- if '/' in each:
- each = each.split('/')[0]
- if socket.inet_pton(socket.AF_INET6, each):
- filtered_ipv6_list.append(each)
- return filtered_ipv6_list
- except socket.error:
- module.fail_json(msg='Incorrect IPV6 address!')
-
-
-def new_dict_to_set(input_dict, temp_list, test_set, count=0):
- # recursive function to convert input dict to set for comparision
- test_dict = dict()
- if isinstance(input_dict, dict):
- input_dict_len = len(input_dict)
- for k, v in sorted(iteritems(input_dict)):
- count += 1
- if isinstance(v, list):
- temp_list.append(k)
- for each in v:
- if isinstance(each, dict):
- if [True for i in each.values() if type(i) == list]:
- new_dict_to_set(each, temp_list, test_set, count)
- else:
- new_dict_to_set(each, temp_list, test_set, 0)
- else:
- if v is not None:
- test_dict.update({k: v})
- try:
- if tuple(iteritems(test_dict)) not in test_set and count == input_dict_len:
- test_set.add(tuple(iteritems(test_dict)))
- count = 0
- except TypeError:
- temp_dict = {}
-
- def expand_dict(dict_to_expand):
- temp = dict()
- for k, v in iteritems(dict_to_expand):
- if isinstance(v, dict):
- expand_dict(v)
- else:
- if v is not None:
- temp.update({k: v})
- temp_dict.update(tuple(iteritems(temp)))
- new_dict = {k: v}
- expand_dict(new_dict)
- if tuple(iteritems(temp_dict)) not in test_set:
- test_set.add(tuple(iteritems(temp_dict)))
-
-
-def dict_to_set(sample_dict):
- # Generate a set with passed dictionary for comparison
- test_dict = dict()
- if isinstance(sample_dict, dict):
- for k, v in iteritems(sample_dict):
- if v is not None:
- if isinstance(v, list):
- if isinstance(v[0], dict):
- li = []
- for each in v:
- for key, value in iteritems(each):
- if isinstance(value, list):
- each[key] = tuple(value)
- li.append(tuple(iteritems(each)))
- v = tuple(li)
- else:
- v = tuple(v)
- elif isinstance(v, dict):
- li = []
- for key, value in iteritems(v):
- if isinstance(value, list):
- v[key] = tuple(value)
- li.extend(tuple(iteritems(v)))
- v = tuple(li)
- test_dict.update({k: v})
- return_set = set(tuple(iteritems(test_dict)))
- else:
- return_set = set(sample_dict)
- return return_set
-
-
-def filter_dict_having_none_value(want, have):
- # Generate dict with have dict value which is None in want dict
- test_dict = dict()
- name = want.get('name')
- if name:
- test_dict['name'] = name
- diff_ip = False
- for k, v in iteritems(want):
- if isinstance(v, dict):
- for key, value in iteritems(v):
- test_key_dict = dict()
- if value is None:
- dict_val = have.get(k).get(key)
- test_key_dict.update({key: dict_val})
- elif k == 'ipv6' and value.lower() != have.get(k)[0].get(key).lower():
- # as multiple IPV6 address can be configured on same
- # interface, for replace state in place update will
- # actually create new entry, which isn't as expected
- # for replace state, so in case of IPV6 address
- # every time 1st delete the existing IPV6 config and
- # then apply the new change
- dict_val = have.get(k)[0].get(key)
- test_key_dict.update({key: dict_val})
- if test_key_dict:
- test_dict.update({k: test_key_dict})
- if isinstance(v, list):
- for key, value in iteritems(v[0]):
- test_key_dict = dict()
- if value is None:
- dict_val = have.get(k).get(key)
- test_key_dict.update({key: dict_val})
- elif k == 'ipv6' and value.lower() != have.get(k)[0].get(key).lower():
- dict_val = have.get(k)[0].get(key)
- test_key_dict.update({key: dict_val})
- if test_key_dict:
- test_dict.update({k: test_key_dict})
- # below conditions checks are added to check if
- # secondary IP is configured, if yes then delete
- # the already configured IP if want and have IP
- # is different else if it's same no need to delete
- for each in v:
- if each.get('secondary'):
- want_ip = each.get('address').split('/')
- have_ip = have.get('ipv4')
- if len(want_ip) > 1 and have_ip and have_ip[0].get('secondary'):
- have_ip = have_ip[0]['address'].split(' ')[0]
- if have_ip != want_ip[0]:
- diff_ip = True
- if each.get('secondary') and diff_ip is True:
- test_key_dict.update({'secondary': True})
- test_dict.update({'ipv4': test_key_dict})
- if v is None:
- val = have.get(k)
- test_dict.update({k: val})
- return test_dict
-
-
-def remove_duplicate_interface(commands):
- # Remove duplicate interface from commands
- set_cmd = []
- for each in commands:
- if 'interface' in each:
- if each not in set_cmd:
- set_cmd.append(each)
- else:
- set_cmd.append(each)
-
- return set_cmd
-
-
-def validate_ipv4(value, module):
- if value:
- address = value.split('/')
- if len(address) != 2:
- module.fail_json(msg='address format is <ipv4 address>/<mask>, got invalid format {0}'.format(value))
-
- if not is_masklen(address[1]):
- module.fail_json(msg='invalid value for mask: {0}, mask should be in range 0-32'.format(address[1]))
-
-
-def validate_ipv6(value, module):
- if value:
- address = value.split('/')
- if len(address) != 2:
- module.fail_json(msg='address format is <ipv6 address>/<mask>, got invalid format {0}'.format(value))
- else:
- if not 0 <= int(address[1]) <= 128:
- module.fail_json(msg='invalid value for mask: {0}, mask should be in range 0-128'.format(address[1]))
-
-
-def validate_n_expand_ipv4(module, want):
- # Check if input IPV4 is valid IP and expand IPV4 with its subnet mask
- ip_addr_want = want.get('address')
- if len(ip_addr_want.split(' ')) > 1:
- return ip_addr_want
- validate_ipv4(ip_addr_want, module)
- ip = ip_addr_want.split('/')
- if len(ip) == 2:
- ip_addr_want = '{0} {1}'.format(ip[0], to_netmask(ip[1]))
-
- return ip_addr_want
-
-
-def netmask_to_cidr(netmask):
- bit_range = [128, 64, 32, 16, 8, 4, 2, 1]
- count = 0
- cidr = 0
- netmask_list = netmask.split('.')
- netmask_calc = [i for i in netmask_list if int(i) != 255 and int(i) != 0]
- if netmask_calc:
- netmask_calc_index = netmask_list.index(netmask_calc[0])
- elif sum(list(map(int, netmask_list))) == 0:
- return '32'
- else:
- return '24'
- for each in bit_range:
- if cidr == int(netmask.split('.')[2]):
- if netmask_calc_index == 1:
- return str(8 + count)
- elif netmask_calc_index == 2:
- return str(8 * 2 + count)
- elif netmask_calc_index == 3:
- return str(8 * 3 + count)
- break
- cidr += each
- count += 1
-
-
-def normalize_interface(name):
- """Return the normalized interface name
- """
- if not name:
- return
-
- def _get_number(name):
- digits = ''
- for char in name:
- if char.isdigit() or char in '/.':
- digits += char
- return digits
-
- if name.lower().startswith('gi'):
- if_type = 'GigabitEthernet'
- elif name.lower().startswith('te'):
- if_type = 'TenGigabitEthernet'
- elif name.lower().startswith('fa'):
- if_type = 'FastEthernet'
- elif name.lower().startswith('fo'):
- if_type = 'FortyGigabitEthernet'
- elif name.lower().startswith('long'):
- if_type = 'LongReachEthernet'
- elif name.lower().startswith('et'):
- if_type = 'Ethernet'
- elif name.lower().startswith('vl'):
- if_type = 'Vlan'
- elif name.lower().startswith('lo'):
- if_type = 'loopback'
- elif name.lower().startswith('po'):
- if_type = 'Port-channel'
- elif name.lower().startswith('nv'):
- if_type = 'nve'
- elif name.lower().startswith('twe'):
- if_type = 'TwentyFiveGigE'
- elif name.lower().startswith('hu'):
- if_type = 'HundredGigE'
- else:
- if_type = None
-
- number_list = name.split(' ')
- if len(number_list) == 2:
- number = number_list[-1].strip()
- else:
- number = _get_number(name)
-
- if if_type:
- proper_interface = if_type + number
- else:
- proper_interface = name
-
- return proper_interface
-
-
-def get_interface_type(interface):
- """Gets the type of interface
- """
-
- if interface.upper().startswith('GI'):
- return 'GigabitEthernet'
- elif interface.upper().startswith('TE'):
- return 'TenGigabitEthernet'
- elif interface.upper().startswith('FA'):
- return 'FastEthernet'
- elif interface.upper().startswith('FO'):
- return 'FortyGigabitEthernet'
- elif interface.upper().startswith('LON'):
- return 'LongReachEthernet'
- elif interface.upper().startswith('ET'):
- return 'Ethernet'
- elif interface.upper().startswith('VL'):
- return 'Vlan'
- elif interface.upper().startswith('LO'):
- return 'loopback'
- elif interface.upper().startswith('PO'):
- return 'Port-channel'
- elif interface.upper().startswith('NV'):
- return 'nve'
- elif interface.upper().startswith('TWE'):
- return 'TwentyFiveGigE'
- elif interface.upper().startswith('HU'):
- return 'HundredGigE'
- else:
- return 'unknown'