diff options
Diffstat (limited to 'lib/ansible/module_utils')
35 files changed, 0 insertions, 4671 deletions
diff --git a/lib/ansible/module_utils/network/junos/argspec/facts/facts.py b/lib/ansible/module_utils/network/junos/argspec/facts/facts.py deleted file mode 100644 index 5b90f847e9..0000000000 --- a/lib/ansible/module_utils/network/junos/argspec/facts/facts.py +++ /dev/null @@ -1,22 +0,0 @@ -# -# -*- coding: utf-8 -*- -# Copyright 2019 Red Hat -# GNU General Public License v3.0+ -# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -""" -The arg spec for the junos facts module. -""" - - -class FactsArgs(object): - """ The arg spec for the junos facts module - """ - - def __init__(self, **kwargs): - pass - - argument_spec = { - 'gather_subset': dict(default=['!config'], type='list'), - 'config_format': dict(default='text', choices=['xml', 'text', 'set', 'json']), - 'gather_network_resources': dict(type='list'), - } diff --git a/lib/ansible/module_utils/network/junos/argspec/interfaces/interfaces.py b/lib/ansible/module_utils/network/junos/argspec/interfaces/interfaces.py deleted file mode 100644 index 5710a07500..0000000000 --- a/lib/ansible/module_utils/network/junos/argspec/interfaces/interfaces.py +++ /dev/null @@ -1,56 +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 junos_interfaces module -""" -from __future__ import absolute_import, division, print_function -__metaclass__ = type - - -class InterfacesArgs(object): - """The arg spec for the junos_interfaces module - """ - - def __init__(self, **kwargs): - pass - - argument_spec = {'config': {'elements': 'dict', - 'options': {'description': {'type': 'str'}, - 'duplex': {'choices': ['automatic', - 'full-duplex', - 'half-duplex'], - 'type': 'str'}, - 'enabled': {'default': True, 'type': 'bool'}, - 'hold_time': {'options': {'down': {'type': 'int'}, - 'up': {'type': 'int'}}, - 'required_together': [['down', 'up']], - 'type': 'dict'}, - 'mtu': {'type': 'int'}, - 'name': {'required': True, 'type': 'str'}, - 'speed': {'type': 'str'}}, - 'type': 'list'}, - 'state': {'choices': ['merged', 'replaced', 'overridden', 'deleted'], - 'default': 'merged', - 'type': 'str'}} diff --git a/lib/ansible/module_utils/network/junos/argspec/l2_interfaces/l2_interfaces.py b/lib/ansible/module_utils/network/junos/argspec/l2_interfaces/l2_interfaces.py deleted file mode 100644 index 1afad9e923..0000000000 --- a/lib/ansible/module_utils/network/junos/argspec/l2_interfaces/l2_interfaces.py +++ /dev/null @@ -1,49 +0,0 @@ -# -# -*- coding: utf-8 -*- -# Copyright 2019 Red Hat -# GNU General Public License v3.0+ -# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -############################################# -# WARNING # -############################################# -# -# This file is auto generated by the resource -# module builder playbook. -# -# Do not edit this file manually. -# -# Changes to this file will be over written -# by the resource module builder. -# -# Changes should be made in the model used to -# generate this file or in the resource module -# builder template. -# -############################################# - -""" -The arg spec for the junos_l2_interfaces module -""" -from __future__ import absolute_import, division, print_function -__metaclass__ = type - - -class L2_interfacesArgs(object): - """The arg spec for the junos_l2_interfaces module - """ - - def __init__(self, **kwargs): - pass - - argument_spec = {'config': {'elements': 'dict', - 'options': {'access': {'type': 'dict', 'options': {'vlan': {'type': 'str'}}}, - 'name': {'required': True, 'type': 'str'}, - 'trunk': {'type': 'dict', 'options': {'allowed_vlans': {'type': 'list'}, - 'native_vlan': {'type': 'str'}}}, - 'unit': {'type': 'int'}, - 'enhanced_layer': {'type': 'bool'}}, - 'type': 'list'}, - 'state': {'choices': ['merged', 'replaced', 'overridden', 'deleted'], - 'default': 'merged', - 'type': 'str'}} diff --git a/lib/ansible/module_utils/network/junos/argspec/l3_interfaces/l3_interfaces.py b/lib/ansible/module_utils/network/junos/argspec/l3_interfaces/l3_interfaces.py deleted file mode 100644 index a6e8bbf9ea..0000000000 --- a/lib/ansible/module_utils/network/junos/argspec/l3_interfaces/l3_interfaces.py +++ /dev/null @@ -1,37 +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 junos_l3_interfaces module -""" -from __future__ import absolute_import, division, print_function -__metaclass__ = type - - -class L3_interfacesArgs(object): # pylint: disable=R0903 - """The arg spec for the junos_l3_interfaces module - """ - - def __init__(self, **kwargs): - pass - - argument_spec = {'config': {'elements': 'dict', 'options': - { - 'ipv4': {'elements': 'dict', - 'options': - {'address': {'type': 'str'}}, - 'type': 'list'}, - 'ipv6': {'elements': 'dict', - 'options': - {'address': {'type': 'str'}}, - 'type': 'list'}, - 'name': {'required': True, 'type': 'str'}, - 'unit': {'type': 'int', 'default': 0} - }, - 'type': 'list'}, - 'state': {'choices': - ['merged', 'replaced', 'overridden', 'deleted'], - 'default': 'merged', - 'type': 'str'}} # pylint: disable=C0301 diff --git a/lib/ansible/module_utils/network/junos/argspec/lacp/lacp.py b/lib/ansible/module_utils/network/junos/argspec/lacp/lacp.py deleted file mode 100644 index e807d66639..0000000000 --- a/lib/ansible/module_utils/network/junos/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 junos_lacp module -""" -from __future__ import absolute_import, division, print_function -__metaclass__ = type - - -class LacpArgs(object): - """The arg spec for the junos_lacp module - """ - - def __init__(self, **kwargs): - pass - - argument_spec = {'config': {'type': 'dict', - 'options': {'link_protection': {'choices': ['revertive', - 'non-revertive'], - 'type': 'str'}, - 'system_priority': {'type': 'int'}}, - }, - 'state': {'choices': ['merged', 'replaced', 'deleted'], - 'default': 'merged', - 'type': 'str'}} diff --git a/lib/ansible/module_utils/network/junos/argspec/lacp_interfaces/lacp_interfaces.py b/lib/ansible/module_utils/network/junos/argspec/lacp_interfaces/lacp_interfaces.py deleted file mode 100644 index 94d6e666bd..0000000000 --- a/lib/ansible/module_utils/network/junos/argspec/lacp_interfaces/lacp_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 junos_lacp_interfaces module -""" -from __future__ import absolute_import, division, print_function -__metaclass__ = type - - -class Lacp_interfacesArgs(object): - """The arg spec for the junos_lacp_interfaces module - """ - - def __init__(self, **kwargs): - pass - - argument_spec = {'config': {'elements': 'dict', - 'options': {'force_up': {'type': 'bool'}, - 'name': {'type': 'str'}, - 'period': {'choices': ['fast', 'slow']}, - 'port_priority': {'type': 'int'}, - 'sync_reset': {'choices': ['disable', 'enable'], - 'type': 'str'}, - 'system': {'options': {'mac': {'type': 'dict', - 'options': {'address': {'type': 'str'}}}, - 'priority': {'type': 'int'}}, - 'type': 'dict'}}, - 'type': 'list'}, - 'state': {'choices': ['merged', 'replaced', 'overridden', 'deleted'], - 'default': 'merged', - 'type': 'str'}} diff --git a/lib/ansible/module_utils/network/junos/argspec/lag_interfaces/lag_interfaces.py b/lib/ansible/module_utils/network/junos/argspec/lag_interfaces/lag_interfaces.py deleted file mode 100644 index 87e677e6f8..0000000000 --- a/lib/ansible/module_utils/network/junos/argspec/lag_interfaces/lag_interfaces.py +++ /dev/null @@ -1,51 +0,0 @@ -# -# -*- coding: utf-8 -*- -# Copyright 2019 Red Hat -# GNU General Public License v3.0+ -# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -############################################# -# WARNING # -############################################# -# -# This file is auto generated by the resource -# module builder playbook. -# -# Do not edit this file manually. -# -# Changes to this file will be over written -# by the resource module builder. -# -# Changes should be made in the model used to -# generate this file or in the resource module -# builder template. -# -############################################# - -""" -The arg spec for the junos_lag_interfaces module -""" -from __future__ import absolute_import, division, print_function -__metaclass__ = type - - -class Lag_interfacesArgs(object): - """The arg spec for the junos_lag_interfaces module - """ - - def __init__(self, **kwargs): - pass - - argument_spec = {'config': {'elements': 'dict', - 'options': {'members': {'elements': 'dict', - 'options': {'link_type': {'choices': ['primary', - 'backup']}, - 'member': {'type': 'str'}}, - 'type': 'list'}, - 'mode': {'choices': ['active', 'passive']}, - 'name': {'required': True, 'type': 'str'}, - 'link_protection': {'type': 'bool'}}, - 'type': 'list'}, - 'state': {'choices': ['merged', 'replaced', 'overridden', 'deleted'], - 'default': 'merged', - 'type': 'str'}} diff --git a/lib/ansible/module_utils/network/junos/argspec/lldp_global/lldp_global.py b/lib/ansible/module_utils/network/junos/argspec/lldp_global/lldp_global.py deleted file mode 100644 index 215d02bae5..0000000000 --- a/lib/ansible/module_utils/network/junos/argspec/lldp_global/lldp_global.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 junos_lldp module -""" -from __future__ import absolute_import, division, print_function -__metaclass__ = type - - -class Lldp_globalArgs(object): - """The arg spec for the junos_lldp module - """ - - def __init__(self, **kwargs): - pass - - argument_spec = {'config': {'options': {'address': {'type': 'str'}, - 'enabled': {'type': 'bool'}, - 'hold_multiplier': {'type': 'int'}, - 'interval': {'type': 'int'}, - 'transmit_delay': {'type': 'int'}}, - 'type': 'dict'}, - 'state': {'choices': ['merged', 'replaced', 'deleted'], - 'default': 'merged', - 'type': 'str'}} diff --git a/lib/ansible/module_utils/network/junos/argspec/lldp_interfaces/lldp_interfaces.py b/lib/ansible/module_utils/network/junos/argspec/lldp_interfaces/lldp_interfaces.py deleted file mode 100644 index 0b62276833..0000000000 --- a/lib/ansible/module_utils/network/junos/argspec/lldp_interfaces/lldp_interfaces.py +++ /dev/null @@ -1,45 +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 junos_lldp_interfaces module -""" -from __future__ import absolute_import, division, print_function -__metaclass__ = type - - -class Lldp_interfacesArgs(object): - """The arg spec for the junos_lldp_interfaces module - """ - - def __init__(self, **kwargs): - pass - - argument_spec = {'config': {'elements': 'dict', - 'options': {'enabled': {'type': 'bool'}, - 'name': {'required': True, 'type': 'str'}}, - 'type': 'list'}, - 'state': {'choices': ['merged', 'replaced', 'deleted', 'overridden'], - 'default': 'merged', - 'type': 'str'}} diff --git a/lib/ansible/module_utils/network/junos/argspec/static_routes/static_routes.py b/lib/ansible/module_utils/network/junos/argspec/static_routes/static_routes.py deleted file mode 100644 index f4179024e5..0000000000 --- a/lib/ansible/module_utils/network/junos/argspec/static_routes/static_routes.py +++ /dev/null @@ -1,73 +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 junos_static_routes module -""" -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - - -class Static_routesArgs(object): # pylint: disable=R0903 - """The arg spec for the junos_static_routes module - """ - - def __init__(self, **kwargs): - pass - - argument_spec = { - 'config': { - 'elements': 'dict', - 'options': { - 'address_families': { - 'elements': 'dict', - 'options': { - 'afi': { - 'choices': ['ipv4', 'ipv6'], - 'required': True, - 'type': 'str'}, - 'routes': {'elements': 'dict', - 'options': { - 'dest': { - 'type': 'str'}, - 'metric': { - 'type': 'int'}, - 'next_hop': { - 'elements': 'dict', - 'options': { - 'forward_router_address': { - 'type': 'str'}}, - 'type': 'list'}}, - 'type': 'list'}}, - 'type': 'list'}, - 'vrf': { - 'type': 'str'}}, - 'type': 'list'}, - 'state': { - 'choices': ['merged', - 'replaced', - 'overridden', - 'deleted'], - 'default': 'merged', - 'type': 'str'}} # pylint: disable=C0301 diff --git a/lib/ansible/module_utils/network/junos/argspec/vlans/vlans.py b/lib/ansible/module_utils/network/junos/argspec/vlans/vlans.py deleted file mode 100644 index 54a28c9889..0000000000 --- a/lib/ansible/module_utils/network/junos/argspec/vlans/vlans.py +++ /dev/null @@ -1,49 +0,0 @@ -# -# -*- coding: utf-8 -*- -# Copyright 2019 Red Hat -# GNU General Public License v3.0+ -# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -############################################# -# WARNING # -############################################# -# -# This file is auto generated by the resource -# module builder playbook. -# -# Do not edit this file manually. -# -# Changes to this file will be over written -# by the resource module builder. -# -# Changes should be made in the model used to -# generate this file or in the resource module -# builder template. -# -############################################# - -""" -The arg spec for the junos_vlans module -""" -from __future__ import absolute_import, division, print_function -__metaclass__ = type - - -class VlansArgs(object): # pylint: disable=R0903 - """The arg spec for the junos_vlans module - """ - - def __init__(self, **kwargs): - pass - - argument_spec = {'config': {'elements': 'dict', - 'options': { - 'description': {}, - 'name': {'required': True, 'type': 'str'}, - 'vlan_id': {'type': 'int'}}, - 'type': 'list'}, - 'state': { - 'choices': ['merged', 'replaced', 'overridden', - 'deleted'], - 'default': 'merged', - 'type': 'str'}} # pylint: disable=C0301 diff --git a/lib/ansible/module_utils/network/junos/config/interfaces/interfaces.py b/lib/ansible/module_utils/network/junos/config/interfaces/interfaces.py deleted file mode 100644 index ea0441041b..0000000000 --- a/lib/ansible/module_utils/network/junos/config/interfaces/interfaces.py +++ /dev/null @@ -1,238 +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 junos_interfaces class -It is in this file where the current configuration (as dict) -is compared to the provided configuration (as dict) and the command set -necessary to bring the current configuration to it's desired end-state is -created -""" -from __future__ import absolute_import, division, print_function -__metaclass__ = type - -from ansible.module_utils.network.common.utils import to_list - -from ansible.module_utils.network.common.cfg.base import ConfigBase -from ansible.module_utils.network.junos.junos import locked_config, load_config, commit_configuration, discard_changes, tostring -from ansible.module_utils.network.junos.facts.facts import Facts -from ansible.module_utils.network.common.netconf import build_root_xml_node, build_child_xml_node - - -class Interfaces(ConfigBase): - """ - The junos_interfaces class - """ - - gather_subset = [ - '!all', - '!min', - ] - - gather_network_resources = [ - 'interfaces', - ] - - 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 module execution - """ - result = {'changed': False} - - existing_interfaces_facts = self.get_interfaces_facts() - - config_xmls = self.set_config(existing_interfaces_facts) - with locked_config(self._module): - for config_xml in to_list(config_xmls): - diff = load_config(self._module, config_xml, []) - - commit = not self._module.check_mode - if diff: - if commit: - commit_configuration(self._module) - else: - discard_changes(self._module) - result['changed'] = True - - if self._module._diff: - result['diff'] = {'prepared': diff} - - result['commands'] = config_xmls - - changed_interfaces_facts = self.get_interfaces_facts() - - result['before'] = existing_interfaces_facts - if result['changed']: - result['after'] = changed_interfaces_facts - - 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 list xml configuration necessary to migrate the current configuration - to the desired configuration - """ - root = build_root_xml_node('interfaces') - state = self._module.params['state'] - if state == 'overridden': - config_xmls = self._state_overridden(want, have) - elif state == 'deleted': - config_xmls = self._state_deleted(want, have) - elif state == 'merged': - config_xmls = self._state_merged(want, have) - elif state == 'replaced': - config_xmls = self._state_replaced(want, have) - - for xml in config_xmls: - root.append(xml) - - return tostring(root) - - def _state_replaced(self, want, have): - """ The xml configuration generator when state is replaced - - :rtype: A list - :returns: the xml configuration necessary to migrate the current configuration - to the desired configuration - """ - intf_xml = [] - intf_xml.extend(self._state_deleted(want, have)) - intf_xml.extend(self._state_merged(want, have)) - - return intf_xml - - def _state_overridden(self, want, have): - """ The xml configuration generator when state is overridden - - :rtype: A list - :returns: the xml configuration necessary to migrate the current configuration - to the desired configuration - """ - interface_xmls_obj = [] - # replace interface config with data in want - interface_xmls_obj.extend(self._state_replaced(want, have)) - - # delete interface config if interface in have not present in want - delete_obj = [] - for have_obj in have: - for want_obj in want: - if have_obj['name'] == want_obj['name']: - break - else: - delete_obj.append(have_obj) - - if delete_obj: - interface_xmls_obj.extend(self._state_deleted(delete_obj, have)) - return interface_xmls_obj - - def _state_merged(self, want, have): - """ The xml configuration generator when state is merged - - :rtype: A list - :returns: the xml configuration necessary to merge the provided into - the current configuration - """ - intf_xml = [] - - for config in want: - intf = build_root_xml_node('interface') - build_child_xml_node(intf, 'name', config['name']) - - intf_fields = ['description', 'speed'] - if not config['name'].startswith('fxp'): - intf_fields.append('mtu') - for field in intf_fields: - if config.get(field): - build_child_xml_node(intf, field, config[field]) - - if config.get('duplex'): - build_child_xml_node(intf, 'link-mode', config['duplex']) - - if config.get('enabled') is False: - build_child_xml_node(intf, 'disable') - - holdtime = config.get('hold_time') - if holdtime: - holdtime_ele = build_child_xml_node(intf, 'hold-time') - - for holdtime_field in ['up', 'down']: - build_child_xml_node(holdtime_ele, holdtime_field, holdtime.get(holdtime_field, '')) - intf_xml.append(intf) - - return intf_xml - - def _state_deleted(self, want, have): - """ The xml configuration generator when state is deleted - - :rtype: A list - :returns: the xml configuration necessary to remove the current configuration - of the provided objects - """ - intf_xml = [] - intf_obj = want - - if not intf_obj: - # delete base interfaces attribute from all the existing interface - intf_obj = have - - for config in intf_obj: - intf = build_root_xml_node('interface') - build_child_xml_node(intf, 'name', config['name']) - - intf_fields = ['description'] - if not config['name'].startswith('lo'): - intf_fields.append('speed') - - if not any([config['name'].startswith('fxp'), config['name'].startswith('lo')]): - intf_fields.append('mtu') - - for field in intf_fields: - build_child_xml_node(intf, field, None, {'delete': 'delete'}) - - if not config['name'].startswith('lo'): - build_child_xml_node(intf, 'link-mode', None, {'delete': 'delete'}) - - build_child_xml_node(intf, 'disable', None, {'delete': 'delete'}) - - holdtime_ele = build_child_xml_node(intf, 'hold-time') - for holdtime_field in ['up', 'down']: - build_child_xml_node(holdtime_ele, holdtime_field, None, {'delete': 'delete'}) - intf_xml.append(intf) - - return intf_xml diff --git a/lib/ansible/module_utils/network/junos/config/l2_interfaces/l2_interfaces.py b/lib/ansible/module_utils/network/junos/config/l2_interfaces/l2_interfaces.py deleted file mode 100644 index 9537e28406..0000000000 --- a/lib/ansible/module_utils/network/junos/config/l2_interfaces/l2_interfaces.py +++ /dev/null @@ -1,256 +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 junos_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.utils import to_list - -from ansible.module_utils.network.common.cfg.base import ConfigBase -from ansible.module_utils.network.junos.junos import locked_config, load_config, commit_configuration, discard_changes, tostring -from ansible.module_utils.network.junos.facts.facts import Facts -from ansible.module_utils.network.junos.utils.utils import get_resource_config -from ansible.module_utils.network.common.netconf import build_root_xml_node, build_child_xml_node, build_subtree - - -class L2_interfaces(ConfigBase): - """ - The junos_l2_interfaces class - """ - - gather_subset = [ - '!all', - '!min', - ] - - gather_network_resources = [ - 'l2_interfaces', - ] - - def __init__(self, module): - super(L2_interfaces, self).__init__(module) - - def get_l2_interfaces_facts(self): - """ Get the 'facts' (the current configuration) - - :rtype: A dictionary - :returns: The current configuration as a dictionary - """ - facts, _warnings = Facts(self._module).get_facts(self.gather_subset, self.gather_network_resources) - l2_interfaces_facts = facts['ansible_network_resources'].get('l2_interfaces') - if not l2_interfaces_facts: - return [] - return l2_interfaces_facts - - def execute_module(self): - """ Execute the module - - :rtype: A dictionary - :returns: The result from module execution - """ - result = {'changed': False} - - existing_l2_interfaces_facts = self.get_l2_interfaces_facts() - - config_xmls = self.set_config(existing_l2_interfaces_facts) - with locked_config(self._module): - for config_xml in to_list(config_xmls): - diff = load_config(self._module, config_xml, []) - - commit = not self._module.check_mode - if diff: - if commit: - commit_configuration(self._module) - else: - discard_changes(self._module) - result['changed'] = True - - if self._module._diff: - result['diff'] = {'prepared': diff} - - result['commands'] = config_xmls - - changed_l2_interfaces_facts = self.get_l2_interfaces_facts() - - result['before'] = existing_l2_interfaces_facts - if result['changed']: - result['after'] = changed_l2_interfaces_facts - - return result - - def set_config(self, existing_l2_interfaces_facts): - """ Collect the configuration from the args passed to the module, - collect the current configuration (as a dict from facts) - - :rtype: A list - :returns: the commands necessary to migrate the current configuration - to the desired configuration - """ - want = self._module.params['config'] - have = existing_l2_interfaces_facts - resp = self.set_state(want, have) - return to_list(resp) - - def set_state(self, want, have): - """ Select the appropriate function based on the state provided - - :param want: the desired configuration as a dictionary - :param have: the current configuration as a dictionary - :rtype: A list - :returns: the list xml configuration necessary to migrate the current configuration - to the desired configuration - """ - root = build_root_xml_node('interfaces') - state = self._module.params['state'] - if state == 'overridden': - config_xmls = self._state_overridden(want, have) - elif state == 'deleted': - config_xmls = self._state_deleted(want, have) - elif state == 'merged': - config_xmls = self._state_merged(want, have) - elif state == 'replaced': - config_xmls = self._state_replaced(want, have) - - for xml in config_xmls: - root.append(xml) - - return tostring(root) - - def _state_replaced(self, want, have): - """ The xml configuration generator when state is replaced - - :rtype: A list - :returns: the xml configuration necessary to migrate the current configuration - to the desired configuration - """ - l2_intf_xml = [] - l2_intf_xml.extend(self._state_deleted(want, have)) - l2_intf_xml.extend(self._state_merged(want, have)) - - return l2_intf_xml - - def _state_overridden(self, want, have): - """ The xml configuration generator when state is overridden - - :rtype: A list - :returns: the xml configuration necessary to migrate the current configuration - to the desired configuration - """ - l2_interface_xmls_obj = [] - # replace interface config with data in want - l2_interface_xmls_obj.extend(self._state_replaced(want, have)) - - # delete interface config if interface in have not present in want - delete_obj = [] - for have_obj in have: - for want_obj in want: - if have_obj['name'] == want_obj['name']: - break - else: - delete_obj.append(have_obj) - - if delete_obj: - l2_interface_xmls_obj.extend(self._state_deleted(delete_obj, have)) - return l2_interface_xmls_obj - - def _state_merged(self, want, have): - """ The xml configuration generator when state is merged - - :rtype: A list - :returns: the xml configuration necessary to merge the provided into - the current configuration - """ - intf_xml = [] - for config in want: - enhanced_layer = True - if config.get('enhanced_layer') is False: - enhanced_layer = False - - mode = 'interface-mode' if enhanced_layer else 'port-mode' - intf = build_root_xml_node('interface') - build_child_xml_node(intf, 'name', config['name']) - unit_node = build_child_xml_node(intf, 'unit') - unit = config['unit'] if config['unit'] else '0' - build_child_xml_node(unit_node, 'name', unit) - - eth_node = build_subtree(unit_node, 'family/ethernet-switching') - if config.get('access'): - vlan = config['access'].get('vlan') - if vlan: - build_child_xml_node(eth_node, mode, 'access') - vlan_node = build_child_xml_node(eth_node, 'vlan') - build_child_xml_node(vlan_node, 'members', vlan) - intf_xml.append(intf) - elif config.get('trunk'): - allowed_vlans = config['trunk'].get('allowed_vlans') - native_vlan = config['trunk'].get('native_vlan') - if allowed_vlans: - build_child_xml_node(eth_node, mode, 'trunk') - vlan_node = build_child_xml_node(eth_node, 'vlan') - for vlan in allowed_vlans: - build_child_xml_node(vlan_node, 'members', vlan) - if native_vlan: - build_child_xml_node(intf, 'native-vlan-id', native_vlan) - - if allowed_vlans or native_vlan: - intf_xml.append(intf) - - return intf_xml - - def _state_deleted(self, want, have): - """ The xml configuration generator when state is deleted - - :rtype: A list - :returns: the xml configuration necessary to remove the current configuration - of the provided objects - """ - l2_intf_xml = [] - l2_intf_obj = want - - config_filter = """ - <configuration> - <interfaces/> - </configuration> - """ - data = get_resource_config(self._connection, config_filter=config_filter) - - if not l2_intf_obj: - # delete l2 interfaces attribute from all the existing interface having l2 config - l2_intf_obj = have - - for config in l2_intf_obj: - name = config['name'] - enhanced_layer = True - l2_mode = data.xpath("configuration/interfaces/interface[name='%s']/unit/family/ethernet-switching/interface-mode" % name) - - if not len(l2_mode): - l2_mode = data.xpath("configuration/interfaces/interface[name='%s']/unit/family/ethernet-switching/port-mode" % name) - enhanced_layer = False - - if len(l2_mode): - mode = 'interface-mode' if enhanced_layer else 'port-mode' - - intf = build_root_xml_node('interface') - build_child_xml_node(intf, 'name', name) - - unit_node = build_child_xml_node(intf, 'unit') - unit = config['unit'] if config['unit'] else '0' - build_child_xml_node(unit_node, 'name', unit) - - eth_node = build_subtree(unit_node, 'family/ethernet-switching') - build_child_xml_node(eth_node, mode, None, {'delete': 'delete'}) - build_child_xml_node(eth_node, 'vlan', None, {'delete': 'delete'}) - build_child_xml_node(intf, 'native-vlan-id', None, {'delete': 'delete'}) - - l2_intf_xml.append(intf) - - return l2_intf_xml diff --git a/lib/ansible/module_utils/network/junos/config/l3_interfaces/l3_interfaces.py b/lib/ansible/module_utils/network/junos/config/l3_interfaces/l3_interfaces.py deleted file mode 100644 index 06db84bd23..0000000000 --- a/lib/ansible/module_utils/network/junos/config/l3_interfaces/l3_interfaces.py +++ /dev/null @@ -1,234 +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 junos_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.junos.facts.facts import Facts -from ansible.module_utils.network.junos.junos import ( - locked_config, load_config, commit_configuration, discard_changes, - tostring) -from ansible.module_utils.network.common.netconf import (build_root_xml_node, - build_child_xml_node) - - -class L3_interfaces(ConfigBase): - """ - The junos_l3_interfaces class - """ - - gather_subset = [ - '!all', - '!min', - ] - - gather_network_resources = [ - 'l3_interfaces', - ] - - def __init__(self, module): - super(L3_interfaces, self).__init__(module) - - 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} - warnings = list() - - existing_interfaces_facts = self.get_l3_interfaces_facts() - - config_xmls = self.set_config(existing_interfaces_facts) - with locked_config(self._module): - for config_xml in to_list(config_xmls): - diff = load_config(self._module, config_xml, warnings) - - commit = not self._module.check_mode - if diff: - if commit: - commit_configuration(self._module) - else: - discard_changes(self._module) - result['changed'] = True - - if self._module._diff: - result['diff'] = {'prepared': diff} - - result['commands'] = config_xmls - - changed_interfaces_facts = self.get_l3_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_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 list xml configuration necessary to migrate the current - configuration - to the desired configuration - """ - root = build_root_xml_node('interfaces') - state = self._module.params['state'] - if state == 'overridden': - config_xmls = self._state_overridden(want, have) - elif state == 'deleted': - config_xmls = self._state_deleted(want, have) - elif state == 'merged': - config_xmls = self._state_merged(want, have) - elif state == 'replaced': - config_xmls = self._state_replaced(want, have) - - for xml in config_xmls: - root.append(xml) - - return tostring(root) - - def _get_common_xml_node(self, name): - root_node = build_root_xml_node('interface') - build_child_xml_node(root_node, 'name', name) - intf_unit_node = build_child_xml_node(root_node, 'unit') - return root_node, intf_unit_node - - def _state_replaced(self, want, have): - """ The xml generator when state is replaced - - :rtype: A list - :returns: the xml necessary to migrate the current configuration - to the desired configuration - """ - intf_xml = [] - intf_xml.extend(self._state_deleted(want, have)) - intf_xml.extend(self._state_merged(want, have)) - return intf_xml - - def _state_overridden(self, want, have): - """ The xml generator when state is overridden - - :rtype: A list - :returns: the xml necessary to migrate the current configuration - to the desired configuration - """ - intf_xml = [] - intf_xml.extend(self._state_deleted(have, have)) - intf_xml.extend(self._state_merged(want, have)) - return intf_xml - - def _state_merged(self, want, have): - """ The xml generator when state is merged - - :rtype: A list - :returns: the xml necessary to merge the provided into - the current configuration - """ - intf_xml = [] - for config in want: - root_node, unit_node = self._get_common_xml_node(config['name']) - build_child_xml_node(unit_node, 'name', - str(config['unit'])) - if config.get('ipv4'): - self.build_ipaddr_et(config, unit_node) - if config.get('ipv6'): - self.build_ipaddr_et(config, unit_node, protocol='ipv6') - intf_xml.append(root_node) - return intf_xml - - def build_ipaddr_et(self, config, unit_node, protocol='ipv4', - delete=False): - family = build_child_xml_node(unit_node, 'family') - inet = 'inet' - if protocol == 'ipv6': - inet = 'inet6' - ip_protocol = build_child_xml_node(family, inet) - for ip_addr in config[protocol]: - if ip_addr['address'] == 'dhcp' and protocol == 'ipv4': - build_child_xml_node(ip_protocol, 'dhcp') - else: - ip_addresses = build_child_xml_node( - ip_protocol, 'address') - build_child_xml_node( - ip_addresses, 'name', ip_addr['address']) - - def _state_deleted(self, want, have): - """ The xml configuration generator when state is deleted - - :rtype: A list - :returns: the xml configuration necessary to remove the current - configuration of the provided objects - """ - intf_xml = [] - existing_l3_intfs = [l3_intf['name'] for l3_intf in have] - - if not want: - want = have - - for config in want: - if config['name'] not in existing_l3_intfs: - continue - else: - root_node, unit_node = self._get_common_xml_node( - config['name']) - build_child_xml_node(unit_node, 'name', - str(config['unit'])) - family = build_child_xml_node(unit_node, 'family') - ipv4 = build_child_xml_node(family, 'inet') - intf = next( - (intf for intf in have if intf['name'] == config['name']), - None) - if 'ipv4' in intf: - if 'dhcp' in [x['address'] for x in intf.get('ipv4') if intf.get('ipv4') is not None]: - build_child_xml_node(ipv4, 'dhcp', None, {'delete': 'delete'}) - else: - build_child_xml_node( - ipv4, 'address', None, {'delete': 'delete'}) - ipv6 = build_child_xml_node(family, 'inet6') - build_child_xml_node(ipv6, 'address', None, {'delete': 'delete'}) - intf_xml.append(root_node) - return intf_xml diff --git a/lib/ansible/module_utils/network/junos/config/lacp/lacp.py b/lib/ansible/module_utils/network/junos/config/lacp/lacp.py deleted file mode 100644 index 875f63880a..0000000000 --- a/lib/ansible/module_utils/network/junos/config/lacp/lacp.py +++ /dev/null @@ -1,185 +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 junos_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.netconf import build_root_xml_node, build_child_xml_node, build_subtree -from ansible.module_utils.network.common.utils import to_list -from ansible.module_utils.network.junos.facts.facts import Facts -from ansible.module_utils.network.junos.junos import locked_config, load_config, commit_configuration, discard_changes, tostring - - -class Lacp(ConfigBase): - """ - The junos_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} - - existing_lacp_facts = self.get_lacp_facts() - config_xmls = self.set_config(existing_lacp_facts) - - with locked_config(self._module): - for config_xml in to_list(config_xmls): - diff = load_config(self._module, config_xml, []) - - commit = not self._module.check_mode - if diff: - if commit: - commit_configuration(self._module) - else: - discard_changes(self._module) - result['changed'] = True - - if self._module._diff: - result['diff'] = {'prepared': diff} - - result['commands'] = config_xmls - - changed_lacp_facts = self.get_lacp_facts() - - result['before'] = existing_lacp_facts - if result['changed']: - result['after'] = changed_lacp_facts - - 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 list xml configuration necessary to migrate the current configuration - to the desired configuration - """ - root = build_root_xml_node('chassis') - ethernet_ele = build_subtree(root, 'aggregated-devices/ethernet') - state = self._module.params['state'] - if state == 'overridden': - config_xmls = self._state_overridden(want, have) - elif state == 'deleted': - config_xmls = self._state_deleted(want, have) - elif state == 'merged': - config_xmls = self._state_merged(want, have) - elif state == 'replaced': - config_xmls = self._state_replaced(want, have) - - for xml in config_xmls: - ethernet_ele.append(xml) - return tostring(root) - - def _state_replaced(self, want, have): - """ The xml configuration generator when state is merged - :rtype: A list - :returns: the xml configuration necessary to merge the provided into - the current configuration - """ - lacp_xml = [] - lacp_xml.extend(self._state_deleted(want, have)) - lacp_xml.extend(self._state_merged(want, have)) - - return lacp_xml - - 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 - """ - lacp_xml = [] - lacp_xml.extend(self._state_deleted(want, have)) - lacp_xml.extend(self._state_merged(want, have)) - - return lacp_xml - - def _state_merged(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 list xml configuration necessary to migrate the current configuration - to the desired configuration - """ - lacp_xml = [] - - lacp_root = build_root_xml_node('lacp') - build_child_xml_node(lacp_root, 'system-priority', want.get('system_priority')) - if want.get('link_protection') == 'non-revertive': - build_subtree(lacp_root, 'link-protection/non-revertive') - elif want.get('link_protection') == 'revertive': - link_root = build_child_xml_node(lacp_root, 'link-protection') - build_child_xml_node(link_root, 'non-revertive', None, {'delete': 'delete'}) - lacp_xml.append(lacp_root) - return lacp_xml - - 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 - """ - lacp_xml = [] - - lacp_root = build_root_xml_node('lacp') - build_child_xml_node(lacp_root, 'system-priority', None, {'delete': 'delete'}) - element = build_child_xml_node(lacp_root, 'link-protection', None, {'delete': 'delete'}) - build_child_xml_node(element, 'non-revertive', None, {'delete': 'delete'}) - - lacp_xml.append(lacp_root) - return lacp_xml diff --git a/lib/ansible/module_utils/network/junos/config/lacp_interfaces/lacp_interfaces.py b/lib/ansible/module_utils/network/junos/config/lacp_interfaces/lacp_interfaces.py deleted file mode 100644 index 62be176df3..0000000000 --- a/lib/ansible/module_utils/network/junos/config/lacp_interfaces/lacp_interfaces.py +++ /dev/null @@ -1,227 +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 junos_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.junos.facts.facts import Facts -from ansible.module_utils.network.junos.junos import locked_config, load_config, commit_configuration, discard_changes, tostring -from ansible.module_utils.network.common.netconf import build_root_xml_node, build_child_xml_node, build_subtree - - -class Lacp_interfaces(ConfigBase): - """ - The junos_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} - - existing_lacp_interfaces_facts = self.get_lacp_interfaces_facts() - config_xmls = self.set_config(existing_lacp_interfaces_facts) - - with locked_config(self._module): - for config_xml in to_list(config_xmls): - diff = load_config(self._module, config_xml, []) - - commit = not self._module.check_mode - if diff: - if commit: - commit_configuration(self._module) - else: - discard_changes(self._module) - result['changed'] = True - - if self._module._diff: - result['diff'] = {'prepared': diff} - - result['commands'] = config_xmls - - changed_lacp_interfaces_facts = self.get_lacp_interfaces_facts() - - result['before'] = existing_lacp_interfaces_facts - if result['changed']: - result['after'] = changed_lacp_interfaces_facts - - 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 - """ - root = build_root_xml_node('interfaces') - state = self._module.params['state'] - if state == 'overridden': - config_xmls = self._state_overridden(want, have) - elif state == 'deleted': - config_xmls = self._state_deleted(want, have) - elif state == 'merged': - config_xmls = self._state_merged(want, have) - elif state == 'replaced': - config_xmls = self._state_replaced(want, have) - - for xml in config_xmls: - root.append(xml) - - return tostring(root) - - def _state_replaced(self, want, have): - """ The xml configuration generator when state is replaced - :rtype: A list - :returns: the xml configuration necessary to migrate the current configuration - to the desired configuration - """ - intf_xml = [] - intf_xml.extend(self._state_deleted(want, have)) - intf_xml.extend(self._state_merged(want, have)) - - return intf_xml - - def _state_overridden(self, want, have): - """ The xml configuration generator when state is overridden - :rtype: A list - :returns: the xml configuration necessary to migrate the current configuration - to the desired configuration - """ - interface_xmls_obj = [] - # replace interface config with data in want - interface_xmls_obj.extend(self._state_replaced(want, have)) - - # delete interface config if interface in have not present in want - delete_obj = [] - for have_obj in have: - for want_obj in want: - if have_obj['name'] == want_obj['name']: - break - else: - delete_obj.append(have_obj) - - if delete_obj: - interface_xmls_obj.extend(self._state_deleted(delete_obj, have)) - return interface_xmls_obj - - def _state_merged(self, want, have): - """ The xml configuration generator when state is merged - :rtype: A list - :returns: the xml configuration necessary to merge the provided into - the current configuration - """ - intf_xml = [] - - for config in want: - lacp_intf_name = config['name'] - lacp_intf_root = build_root_xml_node('interface') - - build_child_xml_node(lacp_intf_root, 'name', lacp_intf_name) - if lacp_intf_name.startswith('ae'): - element = build_subtree(lacp_intf_root, 'aggregated-ether-options/lacp') - if config['period']: - build_child_xml_node(element, 'periodic', config['period']) - if config['sync_reset']: - build_child_xml_node(element, 'sync-reset', config['sync_reset']) - - system = config['system'] - if system: - mac = system.get('mac') - if mac: - if mac.get('address'): - build_child_xml_node(element, 'system-id', mac['address']) - if system.get('priority'): - build_child_xml_node(element, 'system-priority', system['priority']) - intf_xml.append(lacp_intf_root) - elif config['port_priority'] or config['force_up'] is not None: - element = build_subtree(lacp_intf_root, 'ether-options/ieee-802.3ad/lacp') - build_child_xml_node(element, 'port-priority', config['port_priority']) - if config['force_up'] is False: - build_child_xml_node(element, 'force-up', None, {'delete': 'delete'}) - else: - build_child_xml_node(element, 'force-up') - intf_xml.append(lacp_intf_root) - - return intf_xml - - def _state_deleted(self, want, have): - """ The xml configuration generator when state is deleted - :rtype: A list - :returns: the xml configuration necessary to remove the current configuration - of the provided objects - """ - intf_xml = [] - intf_obj = want - - if not intf_obj: - # delete lag interfaces attribute for all the interface - intf_obj = have - - for config in intf_obj: - lacp_intf_name = config['name'] - lacp_intf_root = build_root_xml_node('interface') - build_child_xml_node(lacp_intf_root, 'name', lacp_intf_name) - if lacp_intf_name.startswith('ae'): - element = build_subtree(lacp_intf_root, 'aggregated-ether-options/lacp') - build_child_xml_node(element, 'periodic', None, {'delete': 'delete'}) - build_child_xml_node(element, 'sync-reset', None, {'delete': 'delete'}) - build_child_xml_node(element, 'system-id', None, {'delete': 'delete'}) - build_child_xml_node(element, 'system-priority', None, {'delete': 'delete'}) - else: - element = build_subtree(lacp_intf_root, 'ether-options/ieee-802.3ad/lacp') - build_child_xml_node(element, 'port-priority', None, {'delete': 'delete'}) - build_child_xml_node(element, 'force-up', None, {'delete': 'delete'}) - - intf_xml.append(lacp_intf_root) - - return intf_xml diff --git a/lib/ansible/module_utils/network/junos/config/lag_interfaces/lag_interfaces.py b/lib/ansible/module_utils/network/junos/config/lag_interfaces/lag_interfaces.py deleted file mode 100644 index 3d8fc62941..0000000000 --- a/lib/ansible/module_utils/network/junos/config/lag_interfaces/lag_interfaces.py +++ /dev/null @@ -1,253 +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 junos_lag_interfaces class -It is in this file where the current configuration (as dict) -is compared to the provided configuration (as dict) and the command set -necessary to bring the current configuration to it's desired end-state is -created -""" -from __future__ import absolute_import, division, print_function -__metaclass__ = type - -from ansible.module_utils.network.common.cfg.base import ConfigBase -from ansible.module_utils.network.common.utils import to_list -from ansible.module_utils.network.junos.facts.facts import Facts -from ansible.module_utils.network.junos.junos import locked_config, load_config, commit_configuration, discard_changes, tostring -from ansible.module_utils.network.junos.utils.utils import get_resource_config -from ansible.module_utils.network.common.netconf import build_root_xml_node, build_child_xml_node, build_subtree - - -class Lag_interfaces(ConfigBase): - """ - The junos_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} - warnings = list() - - existing_lag_interfaces_facts = self.get_lag_interfaces_facts() - config_xmls = self.set_config(existing_lag_interfaces_facts) - - with locked_config(self._module): - for config_xml in to_list(config_xmls): - diff = load_config(self._module, config_xml, warnings) - - commit = not self._module.check_mode - if diff: - if commit: - commit_configuration(self._module) - else: - discard_changes(self._module) - result['changed'] = True - - if self._module._diff: - result['diff'] = {'prepared': diff} - - result['commands'] = config_xmls - - changed_lag_interfaces_facts = self.get_lag_interfaces_facts() - - result['before'] = existing_lag_interfaces_facts - if result['changed']: - result['after'] = changed_lag_interfaces_facts - - 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 - """ - root = build_root_xml_node('interfaces') - state = self._module.params['state'] - if state == 'overridden': - config_xmls = self._state_overridden(want, have) - elif state == 'deleted': - config_xmls = self._state_deleted(want, have) - elif state == 'merged': - config_xmls = self._state_merged(want, have) - elif state == 'replaced': - config_xmls = self._state_replaced(want, have) - - for xml in config_xmls: - root.append(xml) - - return tostring(root) - - def _state_replaced(self, want, have): - """ The xml configuration generator when state is replaced - :rtype: A list - :returns: the xml configuration necessary to migrate the current configuration - to the desired configuration - """ - intf_xml = [] - intf_xml.extend(self._state_deleted(want, have)) - intf_xml.extend(self._state_merged(want, have)) - - return intf_xml - - def _state_overridden(self, want, have): - """ The xml configuration generator when state is overridden - :rtype: A list - :returns: the xml configuration necessary to migrate the current configuration - to the desired configuration - """ - interface_xmls_obj = [] - # replace interface config with data in want - interface_xmls_obj.extend(self._state_replaced(want, have)) - - # delete interface config if interface in have not present in want - delete_obj = [] - for have_obj in have: - for want_obj in want: - if have_obj['name'] == want_obj['name']: - break - else: - delete_obj.append(have_obj) - - if delete_obj: - interface_xmls_obj.extend(self._state_deleted(delete_obj, have)) - return interface_xmls_obj - - def _state_merged(self, want, have): - """ The xml configuration generator when state is merged - :rtype: A list - :returns: the xml configuration necessary to merge the provided into - the current configuration - """ - intf_xml = [] - config_filter = """ - <configuration> - <interfaces/> - </configuration> - """ - data = get_resource_config(self._connection, config_filter=config_filter) - - for config in want: - lag_name = config['name'] - - # if lag interface not already configured fail module. - if not data.xpath("configuration/interfaces/interface[name='%s']" % lag_name): - self._module.fail_json(msg="lag interface %s not configured, configure interface" - " %s before assigning members to lag" % (lag_name, lag_name)) - - lag_intf_root = build_root_xml_node('interface') - build_child_xml_node(lag_intf_root, 'name', lag_name) - ether_options_node = build_subtree(lag_intf_root, 'aggregated-ether-options') - if config['mode']: - - lacp_node = build_child_xml_node(ether_options_node, 'lacp') - build_child_xml_node(lacp_node, config['mode']) - - link_protection = config['link_protection'] - if link_protection: - build_child_xml_node(ether_options_node, 'link-protection') - elif link_protection is False: - build_child_xml_node(ether_options_node, 'link-protection', None, {'delete': 'delete'}) - - intf_xml.append(lag_intf_root) - - members = config['members'] - for member in members: - lag_member_intf_root = build_root_xml_node('interface') - build_child_xml_node(lag_member_intf_root, 'name', member['member']) - lag_node = build_subtree(lag_member_intf_root, 'ether-options/ieee-802.3ad') - build_child_xml_node(lag_node, 'bundle', config['name']) - - link_type = member.get('link_type') - if link_type == "primary": - build_child_xml_node(lag_node, 'primary') - elif link_type == "backup": - build_child_xml_node(lag_node, 'backup') - - intf_xml.append(lag_member_intf_root) - - return intf_xml - - def _state_deleted(self, want, have): - """ The xml configuration generator when state is deleted - :rtype: A list - :returns: the xml configuration necessary to remove the current configuration - of the provided objects - """ - intf_xml = [] - intf_obj = want - - if not intf_obj: - # delete lag interfaces attribute for all the interface - intf_obj = have - - for config in intf_obj: - lag_name = config['name'] - lag_intf_root = build_root_xml_node('interface') - build_child_xml_node(lag_intf_root, 'name', lag_name) - - lag_node = build_subtree(lag_intf_root, 'aggregated-ether-options') - build_child_xml_node(lag_node, 'link-protection', None, {'delete': 'delete'}) - - lacp_node = build_child_xml_node(lag_node, 'lacp') - build_child_xml_node(lacp_node, 'active', None, {'delete': 'delete'}) - build_child_xml_node(lacp_node, 'passive', None, {'delete': 'delete'}) - - intf_xml.append(lag_intf_root) - - # delete lag configuration from member interfaces - for interface_obj in have: - if lag_name == interface_obj['name']: - for member in interface_obj.get('members', []): - lag_member_intf_root = build_root_xml_node('interface') - build_child_xml_node(lag_member_intf_root, 'name', member['member']) - lag_node = build_subtree(lag_member_intf_root, 'ether-options/ieee-802.3ad') - build_child_xml_node(lag_node, 'bundle', None, {'delete': 'delete'}) - build_child_xml_node(lag_node, 'primary', None, {'delete': 'delete'}) - build_child_xml_node(lag_node, 'backup', None, {'delete': 'delete'}) - intf_xml.append(lag_member_intf_root) - - return intf_xml diff --git a/lib/ansible/module_utils/network/junos/config/lldp_global/lldp_global.py b/lib/ansible/module_utils/network/junos/config/lldp_global/lldp_global.py deleted file mode 100644 index 57c8b5c627..0000000000 --- a/lib/ansible/module_utils/network/junos/config/lldp_global/lldp_global.py +++ /dev/null @@ -1,177 +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 junos_lldp 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.junos.junos import locked_config, load_config, commit_configuration, discard_changes, tostring -from ansible.module_utils.network.common.utils import to_list -from ansible.module_utils.network.junos.facts.facts import Facts -from ansible.module_utils.network.common.netconf import build_root_xml_node, build_child_xml_node - - -class Lldp_global(ConfigBase): - """ - The junos_lldp class - """ - - gather_subset = [ - '!all', - '!min', - ] - - gather_network_resources = [ - 'lldp_global', - ] - - def __init__(self, module): - super(Lldp_global, self).__init__(module) - - def get_lldp_global_facts(self): - """ 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_facts = facts['ansible_network_resources'].get('lldp_global') - if not lldp_facts: - return {} - return lldp_facts - - def execute_module(self): - """ Execute the module - :rtype: A dictionary - :returns: The result from module execution - """ - result = {'changed': False} - - existing_lldp_global_facts = self.get_lldp_global_facts() - config_xmls = self.set_config(existing_lldp_global_facts) - - with locked_config(self._module): - for config_xml in to_list(config_xmls): - diff = load_config(self._module, config_xml, []) - - commit = not self._module.check_mode - if diff: - if commit: - commit_configuration(self._module) - else: - discard_changes(self._module) - result['changed'] = True - - if self._module._diff: - result['diff'] = {'prepared': diff} - - result['commands'] = config_xmls - - changed_lldp_global_facts = self.get_lldp_global_facts() - - result['before'] = existing_lldp_global_facts - if result['changed']: - result['after'] = changed_lldp_global_facts - - return result - - def set_config(self, existing_lldp_global_facts): - """ Collect the configuration from the args passed to the module, - collect the current configuration (as a dict from facts) - :rtype: A list - :returns: the commands necessary to migrate the current configuration - to the desired configuration - """ - want = self._module.params['config'] - 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 list xml configuration necessary to migrate the current configuration - to the desired configuration - """ - root = build_root_xml_node('protocols') - state = self._module.params['state'] - if state == 'deleted': - config_xmls = self._state_deleted(want, have) - elif state == 'merged': - config_xmls = self._state_merged(want, have) - elif state == 'replaced': - config_xmls = self._state_replaced(want, have) - - for xml in config_xmls: - root.append(xml) - return tostring(root) - - def _state_replaced(self, want, have): - """ The xml configuration generator when state is merged - :rtype: A list - :returns: the xml configuration necessary to merge the provided into - the current configuration - """ - lldp_xml = [] - lldp_xml.extend(self._state_deleted(want, have)) - lldp_xml.extend(self._state_merged(want, have)) - - return lldp_xml - - def _state_merged(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 list xml configuration necessary to migrate the current configuration - to the desired configuration - """ - lldp_xml = [] - - lldp_root = build_root_xml_node('lldp') - if want.get('address'): - build_child_xml_node(lldp_root, 'management-address', want['address']) - if want.get('interval'): - build_child_xml_node(lldp_root, 'advertisement-interval', want['interval']) - if want.get('transmit_delay'): - build_child_xml_node(lldp_root, 'transmit-delay', want['transmit_delay']) - if want.get('hold_multiplier'): - build_child_xml_node(lldp_root, 'hold-multiplier', want['hold_multiplier']) - enable = want.get('enable') - if enable is not None: - if enable is False: - build_child_xml_node(lldp_root, 'disable') - else: - build_child_xml_node(lldp_root, 'disable', None, {'delete': 'delete'}) - else: - build_child_xml_node(lldp_root, 'disable', None, {'delete': 'delete'}) - lldp_xml.append(lldp_root) - - return lldp_xml - - 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 - """ - lldp_xml = [] - - lldp_root = build_root_xml_node('lldp') - build_child_xml_node(lldp_root, 'management-address', None, {'delete': 'delete'}) - build_child_xml_node(lldp_root, 'advertisement-interval', None, {'delete': 'delete'}) - build_child_xml_node(lldp_root, 'transmit-delay', None, {'delete': 'delete'}) - build_child_xml_node(lldp_root, 'hold-multiplier', None, {'delete': 'delete'}) - build_child_xml_node(lldp_root, 'disable', None, {'delete': 'delete'}) - lldp_xml.append(lldp_root) - return lldp_xml diff --git a/lib/ansible/module_utils/network/junos/config/lldp_interfaces/lldp_interfaces.py b/lib/ansible/module_utils/network/junos/config/lldp_interfaces/lldp_interfaces.py deleted file mode 100644 index e494fb182b..0000000000 --- a/lib/ansible/module_utils/network/junos/config/lldp_interfaces/lldp_interfaces.py +++ /dev/null @@ -1,205 +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 junos_lldp_interfaces class -It is in this file where the current configuration (as dict) -is compared to the provided configuration (as dict) and the command set -necessary to bring the current configuration to it's desired end-state is -created -""" -from __future__ import absolute_import, division, print_function -__metaclass__ = type - -from ansible.module_utils.network.common.cfg.base import ConfigBase -from ansible.module_utils.network.common.utils import to_list -from ansible.module_utils.network.junos.facts.facts import Facts -from ansible.module_utils.network.junos.junos import locked_config, load_config, commit_configuration, discard_changes, tostring -from ansible.module_utils.network.common.netconf import build_root_xml_node, build_child_xml_node, build_subtree - - -class Lldp_interfaces(ConfigBase): - """ - The junos_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} - warnings = list() - - existing_lldp_interfaces_facts = self.get_lldp_interfaces_facts() - config_xmls = self.set_config(existing_lldp_interfaces_facts) - - with locked_config(self._module): - for config_xml in to_list(config_xmls): - diff = load_config(self._module, config_xml, warnings) - - commit = not self._module.check_mode - if diff: - if commit: - commit_configuration(self._module) - else: - discard_changes(self._module) - result['changed'] = True - - if self._module._diff: - result['diff'] = {'prepared': diff} - - result['commands'] = config_xmls - - changed_lldp_interfaces_facts = self.get_lldp_interfaces_facts() - - result['before'] = existing_lldp_interfaces_facts - if result['changed']: - result['after'] = changed_lldp_interfaces_facts - - 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 - """ - root = build_root_xml_node('protocols') - lldp_intf_ele = build_subtree(root, 'lldp') - - state = self._module.params['state'] - if state == 'overridden': - config_xmls = self._state_overridden(want, have) - elif state == 'deleted': - config_xmls = self._state_deleted(want, have) - elif state == 'merged': - config_xmls = self._state_merged(want, have) - elif state == 'replaced': - config_xmls = self._state_replaced(want, have) - - for xml in config_xmls: - lldp_intf_ele.append(xml) - - return tostring(root) - - def _state_replaced(self, want, have): - """ The xml configuration generator when state is replaced - :rtype: A list - :returns: the xml configuration necessary to migrate the current configuration - to the desired configuration - """ - lldp_intf_xml = [] - lldp_intf_xml.extend(self._state_deleted(want, have)) - lldp_intf_xml.extend(self._state_merged(want, have)) - - return lldp_intf_xml - - def _state_overridden(self, want, have): - """ The xml configuration generator when state is overridden - :rtype: A list - :returns: the xml configuration necessary to migrate the current configuration - to the desired configuration - """ - lldp_intf_xmls_obj = [] - - # replace interface config with data in want - lldp_intf_xmls_obj.extend(self._state_replaced(want, have)) - - # delete interface config if interface in have not present in want - delete_obj = [] - for have_obj in have: - for want_obj in want: - if have_obj['name'] == want_obj['name']: - break - else: - delete_obj.append(have_obj) - - if len(delete_obj): - lldp_intf_xmls_obj.extend(self._state_deleted(delete_obj, have)) - - return lldp_intf_xmls_obj - - def _state_merged(self, want, have): - """ The xml configuration generator when state is merged - :rtype: A list - :returns: the xml configuration necessary to merge the provided into - the current configuration - """ - lldp_intf_xml = [] - for config in want: - lldp_intf_root = build_root_xml_node('interface') - - if config.get('name'): - build_child_xml_node(lldp_intf_root, 'name', config['name']) - - if config.get('enabled') is not None: - if config['enabled'] is False: - build_child_xml_node(lldp_intf_root, 'disable') - else: - build_child_xml_node(lldp_intf_root, 'disable', None, {'delete': 'delete'}) - else: - build_child_xml_node(lldp_intf_root, 'disable', None, {'delete': 'delete'}) - lldp_intf_xml.append(lldp_intf_root) - return lldp_intf_xml - - def _state_deleted(self, want, have): - """ The xml configuration generator when state is deleted - :rtype: A list - :returns: the xml configuration necessary to remove the current configuration - of the provided objects - """ - lldp_intf_xml = [] - intf_obj = want - - if not intf_obj: - # delete lldp interfaces attribute from all the existing interface - intf_obj = have - - for config in intf_obj: - lldp_intf_root = build_root_xml_node('interface') - lldp_intf_root.attrib.update({'delete': 'delete'}) - build_child_xml_node(lldp_intf_root, 'name', config['name']) - - lldp_intf_xml.append(lldp_intf_root) - - return lldp_intf_xml diff --git a/lib/ansible/module_utils/network/junos/config/static_routes/static_routes.py b/lib/ansible/module_utils/network/junos/config/static_routes/static_routes.py deleted file mode 100644 index 07cce2ff63..0000000000 --- a/lib/ansible/module_utils/network/junos/config/static_routes/static_routes.py +++ /dev/null @@ -1,235 +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 junos_static_routes class -It is in this file where the current configuration (as dict) -is compared to the provided configuration (as dict) and the command set -necessary to bring the current configuration to it's desired end-state is -created -""" -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -from ansible.module_utils.network.common.cfg.base import ConfigBase -from ansible.module_utils.network.common.utils import to_list -from ansible.module_utils.network.junos.facts.facts import Facts -from ansible.module_utils.network.junos.junos import (locked_config, - load_config, - commit_configuration, - discard_changes, - tostring) -from ansible.module_utils.network.common.netconf import (build_root_xml_node, - build_child_xml_node) - - -class Static_routes(ConfigBase): - """ - The junos_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): - """ 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) - static_routes_facts = facts['ansible_network_resources'].get('static_routes') - if not static_routes_facts: - return [] - return static_routes_facts - - def execute_module(self): - """ Execute the module - - :rtype: A dictionary - :returns: The result from module execution - """ - result = {'changed': False} - warnings = list() - - existing_static_routes_facts = self.get_static_routes_facts() - config_xmls = self.set_config(existing_static_routes_facts) - - with locked_config(self._module): - for config_xml in to_list(config_xmls): - diff = load_config(self._module, config_xml, []) - - commit = not self._module.check_mode - if diff: - if commit: - commit_configuration(self._module) - else: - discard_changes(self._module) - result['changed'] = True - - if self._module._diff: - result['diff'] = {'prepared': diff} - - result['xml'] = config_xmls - changed_static_routes_facts = self.get_static_routes_facts() - - result['before'] = existing_static_routes_facts - if result['changed']: - result['after'] = 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'] - root = build_root_xml_node('configuration') - routing_options = build_child_xml_node(root, 'routing-options') - routing_instances = build_child_xml_node(root, 'routing-instances') - if state == 'overridden': - config_xmls = self._state_overridden(want, have) - elif state == 'deleted': - config_xmls = self._state_deleted(want, have) - elif state == 'merged': - config_xmls = self._state_merged(want, have) - elif state == 'replaced': - config_xmls = self._state_replaced(want, have) - - for xml in config_xmls: - if xml['root_type'] == 'routing-options': - routing_options.append(xml['static_route_xml']) - elif xml['root_type'] == 'routing-instances': - routing_instances.append(xml['static_route_xml']) - - return [tostring(xml) for xml in root.getchildren()] - - def _state_replaced(self, want, have): - """ The command generator when state is replaced - - :rtype: A list - :returns: the xml necessary to migrate the current configuration - to the desired configuration - """ - static_route_xml = [] - static_route_xml.extend(self._state_deleted(want, have)) - static_route_xml.extend(self._state_merged(want, have)) - return static_route_xml - - def _state_overridden(self, want, have): - """ The command generator when state is overridden - - :rtype: A list - :returns: the xml necessary to migrate the current configuration - to the desired configuration - """ - static_route_xml = [] - static_route_xml.extend(self._state_deleted(have, have)) - static_route_xml.extend(self._state_merged(want, have)) - return static_route_xml - - def _state_deleted(self, want, have): - """ The command generator when state is deleted - - :rtype: A list - :returns: the xml necessary to migrate the current configuration - to the desired configuration - """ - if not want: - want = have - static_route_xml = self._state_merged(want, have, delete={'delete': 'delete'}) - return static_route_xml - - def _state_merged(self, want, have, delete=None): - """ The command generator when state is merged - - :rtype: A list - :returns: the xml necessary to migrate the current configuration - to the desired configuration - """ - static_route_xml = [] - root_type = "" - vrf_name = None - for config in want: - if config.get('vrf'): - vrf_name = config['vrf'] - if vrf_name: - root_type = 'routing-instances' - instance = build_root_xml_node('instance') - build_child_xml_node(instance, 'name', vrf_name) - routing_options = build_child_xml_node(instance, 'routing-options') - else: - root_type = 'routing-options' - - for afi in config['address_families']: - protocol = afi['afi'] - if protocol == 'ipv6': - if vrf_name: - rib_route_root = build_child_xml_node(routing_options, 'rib') - build_child_xml_node(rib_route_root, 'name', vrf_name + '.inet6.0') - else: - rib_route_root = build_root_xml_node('rib') - build_child_xml_node(rib_route_root, 'name', 'inet6.0') - static_route_root = build_child_xml_node(rib_route_root, 'static') - elif protocol == 'ipv4': - if vrf_name: - static_route_root = build_child_xml_node(routing_options, 'static') - else: - static_route_root = build_root_xml_node('static') - - if afi.get('routes'): - for route in afi['routes']: - route_node = build_child_xml_node(static_route_root, 'route') - if delete: - route_node.attrib.update(delete) - if route.get('dest'): - build_child_xml_node(route_node, 'name', route['dest']) - if not delete: - if route.get('metric'): - build_child_xml_node(route_node, 'metric', route['metric']) - if route.get('next_hop'): - for hop in route['next_hop']: - build_child_xml_node(route_node, 'next-hop', hop['forward_router_address']) - elif delete: - if vrf_name: - instance.attrib.update(delete) - static_route_root.attrib.update(delete) - - if vrf_name: - static_route_xml.append({'root_type': root_type, 'static_route_xml': instance}) - else: - if protocol == 'ipv6': - static_route_xml.append({'root_type': root_type, 'static_route_xml': rib_route_root}) - else: - static_route_xml.append({'root_type': root_type, 'static_route_xml': static_route_root}) - return static_route_xml diff --git a/lib/ansible/module_utils/network/junos/config/vlans/vlans.py b/lib/ansible/module_utils/network/junos/config/vlans/vlans.py deleted file mode 100644 index 70aa5f72fc..0000000000 --- a/lib/ansible/module_utils/network/junos/config/vlans/vlans.py +++ /dev/null @@ -1,208 +0,0 @@ -# Copyright (C) 2019 Red Hat, Inc. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -""" -The junos_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.junos.facts.facts import Facts -from ansible.module_utils.network.junos.junos import (locked_config, - load_config, - commit_configuration, - discard_changes, - tostring) -from ansible.module_utils.network.common.netconf import (build_root_xml_node, - build_child_xml_node) - - -class Vlans(ConfigBase): - """ - The junos_vlans class - """ - - gather_subset = [ - '!all', - '!min', - ] - - gather_network_resources = [ - 'vlans', - ] - - def __init__(self, module): - super(Vlans, self).__init__(module) - - def get_vlans_facts(self): - """ Get the 'facts' (the current configuration) - - :rtype: A dictionary - :returns: The current configuration as a dictionary - """ - facts, _warnings = Facts(self._module).get_facts( - self.gather_subset, self.gather_network_resources) - vlans_facts = facts['ansible_network_resources'].get('vlans') - if not vlans_facts: - return [] - return vlans_facts - - def execute_module(self): - """ Execute the module - - :rtype: A dictionary - :returns: The result from module execution - """ - result = {'changed': False} - warnings = list() - - existing_vlans_facts = self.get_vlans_facts() - config_xmls = self.set_config(existing_vlans_facts) - - with locked_config(self._module): - for config_xml in to_list(config_xmls): - diff = load_config(self._module, config_xml, warnings) - - commit = not self._module.check_mode - if diff: - if commit: - commit_configuration(self._module) - else: - discard_changes(self._module) - result['changed'] = True - - if self._module._diff: - result['diff'] = {'prepared': diff} - - result['commands'] = config_xmls - - changed_vlans_facts = self.get_vlans_facts() - - result['before'] = existing_vlans_facts - if result['changed']: - result['after'] = changed_vlans_facts - - result['warnings'] = warnings - return result - - def set_config(self, existing_vlans_facts): - """ Collect the configuration from the args passed to the module, - collect the current configuration (as a dict from facts) - - :rtype: A list - :returns: the commands necessary to migrate the current configuration - to the desired configuration - """ - want = self._module.params['config'] - have = existing_vlans_facts - resp = self.set_state(want, have) - return to_list(resp) - - def set_state(self, want, have): - """ Select the appropriate function based on the state provided - - :param want: the desired configuration as a dictionary - :param have: the current configuration as a dictionary - :rtype: A list - :returns: the commands necessary to migrate the current configuration - to the desired configuration - """ - root = build_root_xml_node('vlans') - state = self._module.params['state'] - if state == 'overridden': - config_xmls = self._state_overridden(want, have) - elif state == 'deleted': - config_xmls = self._state_deleted(want, have) - elif state == 'merged': - config_xmls = self._state_merged(want, have) - elif state == 'replaced': - config_xmls = self._state_replaced(want, have) - - for xml in config_xmls: - root.append(xml) - - return tostring(root) - - def _state_replaced(self, want, have): - """ The command generator when state is replaced - - :rtype: A list - :returns: the xml necessary to migrate the current configuration - to the desired configuration - """ - intf_xml = [] - intf_xml.extend(self._state_deleted(want, have)) - intf_xml.extend(self._state_merged(want, have)) - return intf_xml - - def _state_overridden(self, want, have): - """ The command generator when state is overridden - - :rtype: A list - :returns: the xml necessary to migrate the current configuration - to the desired configuration - """ - intf_xml = [] - intf_xml.extend(self._state_deleted(have, have)) - intf_xml.extend(self._state_merged(want, have)) - return intf_xml - - def _state_merged(self, want, have): - """ The command generator when state is merged - - :rtype: A list - :returns: the xml necessary to merge the provided into - the current configuration - """ - intf_xml = [] - - for config in want: - vlan_name = str(config['name']) - vlan_id = str(config['vlan_id']) - vlan_description = config.get('description') - vlan_root = build_root_xml_node('vlan') - build_child_xml_node(vlan_root, 'name', vlan_name) - build_child_xml_node(vlan_root, 'vlan-id', vlan_id) - if vlan_description: - build_child_xml_node(vlan_root, 'description', - vlan_description) - intf_xml.append(vlan_root) - return intf_xml - - def _state_deleted(self, want, have): - """ The command generator when state is deleted - - :rtype: A list - :returns: the xml necessary to remove the current configuration - of the provided objects - """ - intf_xml = [] - - if not want: - want = have - - for config in want: - vlan_name = config['name'] - vlan_root = build_root_xml_node('vlan') - vlan_root.attrib.update({'delete': 'delete'}) - build_child_xml_node(vlan_root, 'name', vlan_name) - intf_xml.append(vlan_root) - return intf_xml diff --git a/lib/ansible/module_utils/network/junos/facts/facts.py b/lib/ansible/module_utils/network/junos/facts/facts.py deleted file mode 100644 index 28aa11cf32..0000000000 --- a/lib/ansible/module_utils/network/junos/facts/facts.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 facts class for junos -this file validates each subset of facts and selectively -calls the appropriate facts gathering function -""" - -from ansible.module_utils.network.common.facts.facts import FactsBase -from ansible.module_utils.network.junos.junos import HAS_PYEZ -from ansible.module_utils.network.junos.facts.legacy.base import Default, Hardware, Config, Interfaces, OFacts -from ansible.module_utils.network.junos.facts.interfaces.interfaces import InterfacesFacts -from ansible.module_utils.network.junos.facts.lacp.lacp import LacpFacts -from ansible.module_utils.network.junos.facts.lacp_interfaces.lacp_interfaces import Lacp_interfacesFacts -from ansible.module_utils.network.junos.facts.lag_interfaces.lag_interfaces import Lag_interfacesFacts -from ansible.module_utils.network.junos.facts.l3_interfaces.l3_interfaces import L3_interfacesFacts -from ansible.module_utils.network.junos.facts.lldp_global.lldp_global import Lldp_globalFacts -from ansible.module_utils.network.junos.facts.lldp_interfaces.lldp_interfaces import Lldp_interfacesFacts -from ansible.module_utils.network.junos.facts.vlans.vlans import VlansFacts -from ansible.module_utils.network.junos.facts.l2_interfaces.l2_interfaces import L2_interfacesFacts -from ansible.module_utils.network.junos.facts.static_routes.static_routes import Static_routesFacts - -FACT_LEGACY_SUBSETS = dict( - default=Default, - hardware=Hardware, - config=Config, - interfaces=Interfaces, -) -FACT_RESOURCE_SUBSETS = dict( - interfaces=InterfacesFacts, - lacp=LacpFacts, - lacp_interfaces=Lacp_interfacesFacts, - lag_interfaces=Lag_interfacesFacts, - l2_interfaces=L2_interfacesFacts, - l3_interfaces=L3_interfacesFacts, - lldp_global=Lldp_globalFacts, - lldp_interfaces=Lldp_interfacesFacts, - vlans=VlansFacts, - static_routes=Static_routesFacts -) - - -class Facts(FactsBase): - """ The fact class for junos - """ - - 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 junos - :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 not legacy_facts_type: - legacy_facts_type = self._gather_subset - # fetch old style facts only when explicitly mentioned in gather_subset option - if 'ofacts' in legacy_facts_type: - if HAS_PYEZ: - self.ansible_facts.update(OFacts(self._module).populate()) - else: - self._warnings.extend([ - 'junos-eznc is required to gather old style facts but does not appear to be installed. ' - 'It can be installed using `pip install junos-eznc`']) - self.ansible_facts['ansible_net_gather_subset'].append('ofacts') - legacy_facts_type.remove('ofacts') - - 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/junos/facts/interfaces/interfaces.py b/lib/ansible/module_utils/network/junos/facts/interfaces/interfaces.py deleted file mode 100644 index 6358813e89..0000000000 --- a/lib/ansible/module_utils/network/junos/facts/interfaces/interfaces.py +++ /dev/null @@ -1,111 +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 junos interfaces fact class -It is in this file the configuration is collected from the device -for a given resource, parsed, and the facts tree is populated -based on the configuration. -""" -from __future__ import absolute_import, division, print_function -__metaclass__ = type - -from copy import deepcopy - -from ansible.module_utils._text import to_bytes -from ansible.module_utils.network.common import utils -from ansible.module_utils.network.junos.argspec.interfaces.interfaces import InterfacesArgs -from ansible.module_utils.network.junos.utils.utils import get_resource_config -from ansible.module_utils.six import string_types -try: - from lxml import etree - HAS_LXML = True -except ImportError: - HAS_LXML = False - - -class InterfacesFacts(object): - """ The junos 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 data: previously collected configuration as lxml ElementTree root instance - or valid xml sting - :rtype: dictionary - :returns: facts - """ - if not HAS_LXML: - self._module.fail_json(msg='lxml is not installed.') - - if not data: - config_filter = """ - <configuration> - <interfaces/> - </configuration> - """ - data = get_resource_config(connection, config_filter=config_filter) - - if isinstance(data, string_types): - data = etree.fromstring(to_bytes(data, errors='surrogate_then_replace')) - - resources = data.xpath('configuration/interfaces/interface') - - objs = [] - for resource in resources: - if resource is not None: - obj = self.render_config(self.generated_spec, resource) - 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 ElementTree instance of configuration object - :rtype: dictionary - :returns: The generated config - """ - config = deepcopy(spec) - config['name'] = utils.get_xml_conf_arg(conf, 'name') - config['description'] = utils.get_xml_conf_arg(conf, 'description') - mtu = utils.get_xml_conf_arg(conf, 'mtu') - config['mtu'] = int(mtu) if mtu else None - config['speed'] = utils.get_xml_conf_arg(conf, 'speed') - config['duplex'] = utils.get_xml_conf_arg(conf, 'link-mode') - config['hold_time']['down'] = utils.get_xml_conf_arg(conf, 'hold-time/down') - config['hold_time']['up'] = utils.get_xml_conf_arg(conf, 'hold-time/up') - disable = utils.get_xml_conf_arg(conf, 'disable', data='tag') - if disable: - config['enabled'] = False - else: - config['enabled'] = True - return utils.remove_empties(config) diff --git a/lib/ansible/module_utils/network/junos/facts/l2_interfaces/l2_interfaces.py b/lib/ansible/module_utils/network/junos/facts/l2_interfaces/l2_interfaces.py deleted file mode 100644 index 6416b9ec53..0000000000 --- a/lib/ansible/module_utils/network/junos/facts/l2_interfaces/l2_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 junos l2_interfaces fact class -It is in this file the configuration is collected from the device -for a given resource, parsed, and the facts tree is populated -based on the configuration. -""" -from __future__ import absolute_import, division, print_function -__metaclass__ = type - -from copy import deepcopy - -from ansible.module_utils._text import to_bytes -from ansible.module_utils.network.common import utils -from ansible.module_utils.network.junos.argspec.l2_interfaces.l2_interfaces import L2_interfacesArgs -from ansible.module_utils.network.junos.utils.utils import get_resource_config -from ansible.module_utils.six import string_types -try: - from lxml import etree - HAS_LXML = True -except ImportError: - HAS_LXML = False - - -class L2_interfacesFacts(object): - """ The junos 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 data: previously collected configuration as lxml ElementTree root instance - or valid xml sting - :rtype: dictionary - :returns: facts - """ - if not HAS_LXML: - self._module.fail_json(msg='lxml is not installed.') - - if not data: - config_filter = """ - <configuration> - <interfaces/> - </configuration> - """ - data = get_resource_config(connection, config_filter=config_filter) - - if isinstance(data, string_types): - data = etree.fromstring(to_bytes(data, errors='surrogate_then_replace')) - - self._resources = data.xpath('configuration/interfaces/interface') - - objs = [] - for resource in self._resources: - if resource is not None: - obj = self.render_config(self.generated_spec, resource) - 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 ElementTree instance of configuration object - :rtype: dictionary - :returns: The generated config - """ - config = deepcopy(spec) - - enhanced_layer = True - mode = utils.get_xml_conf_arg(conf, 'unit/family/ethernet-switching/interface-mode') - - if mode is None: - mode = utils.get_xml_conf_arg(conf, 'unit/family/ethernet-switching/port-mode') - enhanced_layer = False - - # Layer 2 is configured on interface - if mode: - config['name'] = utils.get_xml_conf_arg(conf, 'name') - unit = utils.get_xml_conf_arg(conf, 'unit/name') - config['unit'] = unit if unit else 0 - config['enhanced_layer'] = enhanced_layer - - if mode == 'access': - config['access'] = {} - config['access']['vlan'] = utils.get_xml_conf_arg(conf, "unit/family/ethernet-switching/vlan/members") - elif mode == 'trunk': - config['trunk'] = {} - vlan_members = conf.xpath('unit/family/ethernet-switching/vlan/members') - if vlan_members: - config['trunk']['allowed_vlans'] = [] - for vlan_member in vlan_members: - config['trunk']['allowed_vlans'].append(vlan_member.text) - - config['trunk']['native_vlan'] = utils.get_xml_conf_arg(conf, "native-vlan-id") - - return utils.remove_empties(config) diff --git a/lib/ansible/module_utils/network/junos/facts/l3_interfaces/l3_interfaces.py b/lib/ansible/module_utils/network/junos/facts/l3_interfaces/l3_interfaces.py deleted file mode 100644 index a924de9da0..0000000000 --- a/lib/ansible/module_utils/network/junos/facts/l3_interfaces/l3_interfaces.py +++ /dev/null @@ -1,134 +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 junos 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 - -from ansible.module_utils._text import to_bytes -from ansible.module_utils.network.common import utils -from ansible.module_utils.network.junos.argspec.l3_interfaces.l3_interfaces import L3_interfacesArgs -from ansible.module_utils.six import string_types -try: - from lxml import etree - HAS_LXML = True -except ImportError: - HAS_LXML = False - - -class L3_interfacesFacts(object): - """ The junos 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 - """ - if not HAS_LXML: - self._module.fail_json(msg='lxml is not installed.') - - if not data: - config_filter = """ - <configuration> - <interfaces/> - </configuration> - """ - data = connection.get_configuration(filter=config_filter) - - if isinstance(data, string_types): - data = etree.fromstring(to_bytes(data, errors='surrogate_then_replace')) - - resources = data.xpath('configuration/interfaces/interface') - - objs = [] - if resources: - objs = self.parse_l3_if_resources(resources) - - config = [] - if objs: - for l3_if_obj in objs: - config.append(self.render_config( - self.generated_spec, l3_if_obj)) - - facts = {} - facts['l3_interfaces'] = config - - ansible_facts['ansible_network_resources'].update(facts) - return ansible_facts - - def parse_l3_if_resources(self, l3_if_resources): - l3_ifaces = [] - for iface in l3_if_resources: - interface = {} - interface['name'] = iface.find('name').text - if iface.find('description') is not None: - interface['description'] = iface.find('description').text - interface['unit'] = iface.find('unit/name').text - family = iface.find('unit/family/') - if family is not None and family.tag != 'ethernet-switching': - ipv4 = iface.findall('unit/family/inet/address') - dhcp = iface.findall('unit/family/inet/dhcp') - ipv6 = iface.findall('unit/family/inet6/address') - if dhcp: - interface['ipv4'] = [{'address': 'dhcp'}] - if ipv4: - interface['ipv4'] = self.get_ip_addresses(ipv4) - elif not dhcp: - interface['ipv4'] = None - if ipv6: - interface['ipv6'] = self.get_ip_addresses(ipv6) - l3_ifaces.append(interface) - return l3_ifaces - - def get_ip_addresses(self, ip_addr): - address_list = [] - for ip in ip_addr: - for addr in ip: - address_list.append({'address': addr.text}) - return address_list - - def render_config(self, spec, conf): - """ - Render config as dictionary structure and delete keys - from spec for null values - - :param spec: The facts tree, generated from the argspec - :param conf: The configuration - :rtype: dictionary - :returns: The generated config - """ - config = deepcopy(spec) - config['name'] = conf['name'] - config['description'] = conf.get('description') - config['unit'] = conf.get('unit', 0) - config['ipv4'] = conf.get('ipv4') - config['ipv6'] = conf.get('ipv6') - - return utils.remove_empties(config) diff --git a/lib/ansible/module_utils/network/junos/facts/lacp/lacp.py b/lib/ansible/module_utils/network/junos/facts/lacp/lacp.py deleted file mode 100644 index 433198186f..0000000000 --- a/lib/ansible/module_utils/network/junos/facts/lacp/lacp.py +++ /dev/null @@ -1,96 +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 junos 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._text import to_bytes -from ansible.module_utils.network.common import utils -from ansible.module_utils.network.junos.argspec.lacp.lacp import LacpArgs -from ansible.module_utils.network.junos.utils.utils import get_resource_config -from ansible.module_utils.six import string_types -try: - from lxml import etree - HAS_LXML = True -except ImportError: - HAS_LXML = False - - -class LacpFacts(object): - """ The junos 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 interfaces - :param connection: the device connection - :param data: previously collected configuration as lxml ElementTree root instance - or valid xml sting - :rtype: dictionary - :returns: facts - """ - if not HAS_LXML: - self._module.fail_json(msg='lxml is not installed.') - - if not data: - config_filter = """ - <configuration> - <chassis> - <aggregated-devices> - <ethernet> - <lacp> - </lacp> - </ethernet> - </aggregated-devices> - </chassis> - </configuration> - """ - data = get_resource_config(connection, config_filter=config_filter) - - if isinstance(data, string_types): - data = etree.fromstring(to_bytes(data, errors='surrogate_then_replace')) - - facts = {} - config = deepcopy(self.generated_spec) - resources = data.xpath('configuration/chassis/aggregated-devices/ethernet/lacp') - if resources: - - lacp_root = resources[0] - config['system_priority'] = utils.get_xml_conf_arg(lacp_root, 'system-priority') - - if utils.get_xml_conf_arg(lacp_root, 'link-protection/non-revertive', data='tag'): - config['link_protection'] = "non-revertive" - - elif utils.get_xml_conf_arg(lacp_root, 'link-protection'): - config['link_protection'] = "revertive" - - params = utils.validate_config(self.argument_spec, {'config': utils.remove_empties(config)}) - facts['lacp'] = {} - facts['lacp'].update(utils.remove_empties(params['config'])) - - ansible_facts['ansible_network_resources'].update(facts) - - return ansible_facts diff --git a/lib/ansible/module_utils/network/junos/facts/lacp_interfaces/lacp_interfaces.py b/lib/ansible/module_utils/network/junos/facts/lacp_interfaces/lacp_interfaces.py deleted file mode 100644 index c0e33240e3..0000000000 --- a/lib/ansible/module_utils/network/junos/facts/lacp_interfaces/lacp_interfaces.py +++ /dev/null @@ -1,113 +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 junos 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 - -from copy import deepcopy - -from ansible.module_utils._text import to_bytes -from ansible.module_utils.network.common import utils -from ansible.module_utils.network.junos.argspec.lacp_interfaces.lacp_interfaces import Lacp_interfacesArgs -from ansible.module_utils.network.junos.utils.utils import get_resource_config -from ansible.module_utils.six import string_types -try: - from lxml import etree - HAS_LXML = True -except ImportError: - HAS_LXML = False - - -class Lacp_interfacesFacts(object): - """ The junos 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 interfaces - :param connection: the device connection - :param data: previously collected configuration as lxml ElementTree root instance - or valid xml sting - :rtype: dictionary - :returns: facts - """ - if not HAS_LXML: - self._module.fail_json(msg='lxml is not installed.') - - if not data: - config_filter = """ - <configuration> - <interfaces/> - </configuration> - """ - data = get_resource_config(connection, config_filter=config_filter) - - if isinstance(data, string_types): - data = etree.fromstring(to_bytes(data, errors='surrogate_then_replace')) - - self._resources = data.xpath('configuration/interfaces/interface') - - objs = [] - for resource in self._resources: - if resource is not None: - obj = self.render_config(self.generated_spec, resource) - 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 ElementTree instance of configuration object - :rtype: dictionary - :returns: The generated config - """ - config = deepcopy(spec) - config['name'] = utils.get_xml_conf_arg(conf, 'name') - config['period'] = utils.get_xml_conf_arg(conf, 'aggregated-ether-options/lacp/periodic') - config['sync_reset'] = utils.get_xml_conf_arg(conf, 'aggregated-ether-options/lacp/sync-reset') - force_up = utils.get_xml_conf_arg(conf, 'ether-options/ieee-802.3ad/lacp/force-up', data='tag') - if force_up: - config['force_up'] = True - config['port_priority'] = utils.get_xml_conf_arg(conf, 'ether-options/ieee-802.3ad/lacp/port-priority') - config['system']['priority'] = utils.get_xml_conf_arg(conf, 'aggregated-ether-options/lacp/system-priority') - address = utils.get_xml_conf_arg(conf, 'aggregated-ether-options/lacp/system-id') - if address: - config['system'].update({'mac': {'address': address}}) - - lacp_intf_cfg = utils.remove_empties(config) - # if lacp config is not present for interface return empty dict - if len(lacp_intf_cfg) == 1: - return {} - else: - return lacp_intf_cfg diff --git a/lib/ansible/module_utils/network/junos/facts/lag_interfaces/lag_interfaces.py b/lib/ansible/module_utils/network/junos/facts/lag_interfaces/lag_interfaces.py deleted file mode 100644 index 1acaaa2a28..0000000000 --- a/lib/ansible/module_utils/network/junos/facts/lag_interfaces/lag_interfaces.py +++ /dev/null @@ -1,127 +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 junos lag_interfaces fact class -It is in this file the configuration is collected from the device -for a given resource, parsed, and the facts tree is populated -based on the configuration. -""" -from __future__ import absolute_import, division, print_function -__metaclass__ = type - -from copy import deepcopy - -from ansible.module_utils._text import to_bytes -from ansible.module_utils.network.common import utils -from ansible.module_utils.network.junos.argspec.lag_interfaces.lag_interfaces import Lag_interfacesArgs -from ansible.module_utils.network.junos.utils.utils import get_resource_config -from ansible.module_utils.six import string_types -try: - from lxml import etree - HAS_LXML = True -except ImportError: - HAS_LXML = False - - -class Lag_interfacesFacts(object): - """ The junos 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 data: previously collected configuration as lxml ElementTree root instance - or valid xml sting - :rtype: dictionary - :returns: facts - """ - if not HAS_LXML: - self._module.fail_json(msg='lxml is not installed.') - - if not data: - config_filter = """ - <configuration> - <interfaces/> - </configuration> - """ - data = get_resource_config(connection, config_filter=config_filter) - - if isinstance(data, string_types): - data = etree.fromstring(to_bytes(data, errors='surrogate_then_replace')) - - self._resources = data.xpath('configuration/interfaces/interface') - - objs = [] - for resource in self._resources: - if resource is not None: - obj = self.render_config(self.generated_spec, resource) - if obj: - objs.append(obj) - 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 ElementTree instance of configuration object - :rtype: dictionary - :returns: The generated config - """ - config = deepcopy(spec) - intf_name = utils.get_xml_conf_arg(conf, 'name') - if intf_name.startswith('ae'): - config['name'] = intf_name - config['members'] = [] - for interface_obj in self._resources: - lag_interface_member = utils.get_xml_conf_arg(interface_obj, "ether-options/ieee-802.3ad[bundle='%s']/../../name" % intf_name) - if lag_interface_member: - member_config = {} - member_config['member'] = lag_interface_member - if utils.get_xml_conf_arg(interface_obj, "ether-options/ieee-802.3ad/primary", data='tag'): - member_config['link_type'] = "primary" - elif utils.get_xml_conf_arg(interface_obj, "ether-options/ieee-802.3ad/backup", data='tag'): - member_config['link_type'] = "backup" - - if member_config: - config['members'].append(member_config) - - for m in ['active', 'passive']: - if utils.get_xml_conf_arg(conf, "aggregated-ether-options/lacp/%s" % m, data='tag'): - config['mode'] = m - break - - link_protection = utils.get_xml_conf_arg(conf, "aggregated-ether-options/link-protection", data='tag') - if link_protection: - config['link_protection'] = True - - lag_intf_cfg = utils.remove_empties(config) - # if lag interfaces config is not present return empty dict - if len(lag_intf_cfg) == 1: - return {} - else: - return lag_intf_cfg diff --git a/lib/ansible/module_utils/network/junos/facts/legacy/base.py b/lib/ansible/module_utils/network/junos/facts/legacy/base.py deleted file mode 100644 index 61752a37d7..0000000000 --- a/lib/ansible/module_utils/network/junos/facts/legacy/base.py +++ /dev/null @@ -1,195 +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 junos interfaces fact class -It is in this file the configuration is collected from the device -for a given resource, parsed, and the facts tree is populated -based on the configuration. -""" -import platform - -from ansible.module_utils.network.common.netconf import exec_rpc -from ansible.module_utils.network.junos.junos import tostring -from ansible.module_utils.network.junos.junos import get_configuration, get_capabilities, get_device -from ansible.module_utils._text import to_text - - -try: - from lxml.etree import Element, SubElement -except ImportError: - from xml.etree.ElementTree import Element, SubElement - - -class FactsBase(object): - - def __init__(self, module): - self.module = module - self.facts = dict() - self.warnings = [] - - def populate(self): - raise NotImplementedError - - def cli(self, command): - reply = command(self.module, command) - output = reply.find('.//output') - if not output: - self.module.fail_json(msg='failed to retrieve facts for command %s' % command) - return to_text(output.text).strip() - - def rpc(self, rpc): - return exec_rpc(self.module, tostring(Element(rpc))) - - def get_text(self, ele, tag): - try: - return to_text(ele.find(tag).text).strip() - except AttributeError: - pass - - -class Default(FactsBase): - - def populate(self): - self.facts.update(self.platform_facts()) - - reply = self.rpc('get-chassis-inventory') - data = reply.find('.//chassis-inventory/chassis') - self.facts['serialnum'] = self.get_text(data, 'serial-number') - - 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 Config(FactsBase): - - def populate(self): - config_format = self.module.params['config_format'] - reply = get_configuration(self.module, format=config_format) - - if config_format == 'xml': - config = tostring(reply.find('configuration')).strip() - - elif config_format == 'text': - config = self.get_text(reply, 'configuration-text') - - elif config_format == 'json': - config = self.module.from_json(reply.text.strip()) - - elif config_format == 'set': - config = self.get_text(reply, 'configuration-set') - - self.facts['config'] = config - - -class Hardware(FactsBase): - - def populate(self): - - reply = self.rpc('get-system-memory-information') - data = reply.find('.//system-memory-information/system-memory-summary-information') - - self.facts.update({ - 'memfree_mb': int(self.get_text(data, 'system-memory-free')), - 'memtotal_mb': int(self.get_text(data, 'system-memory-total')) - }) - - reply = self.rpc('get-system-storage') - data = reply.find('.//system-storage-information') - - filesystems = list() - for obj in data: - filesystems.append(self.get_text(obj, 'filesystem-name')) - self.facts['filesystems'] = filesystems - - reply = self.rpc('get-route-engine-information') - data = reply.find('.//route-engine-information') - - routing_engines = dict() - for obj in data: - slot = self.get_text(obj, 'slot') - routing_engines.update({slot: {}}) - routing_engines[slot].update({'slot': slot}) - for child in obj: - if child.text != "\n": - routing_engines[slot].update({child.tag.replace("-", "_"): child.text}) - - self.facts['routing_engines'] = routing_engines - - if len(data) > 1: - self.facts['has_2RE'] = True - else: - self.facts['has_2RE'] = False - - reply = self.rpc('get-chassis-inventory') - data = reply.findall('.//chassis-module') - - modules = list() - for obj in data: - mod = dict() - for child in obj: - if child.text != "\n": - mod.update({child.tag.replace("-", "_"): child.text}) - modules.append(mod) - - self.facts['modules'] = modules - - -class Interfaces(FactsBase): - - def populate(self): - ele = Element('get-interface-information') - SubElement(ele, 'detail') - reply = exec_rpc(self.module, tostring(ele)) - - interfaces = {} - - for item in reply[0]: - name = self.get_text(item, 'name') - obj = { - 'oper-status': self.get_text(item, 'oper-status'), - 'admin-status': self.get_text(item, 'admin-status'), - 'speed': self.get_text(item, 'speed'), - 'macaddress': self.get_text(item, 'hardware-physical-address'), - 'mtu': self.get_text(item, 'mtu'), - 'type': self.get_text(item, 'if-type'), - } - - interfaces[name] = obj - - self.facts['interfaces'] = interfaces - - -class OFacts(FactsBase): - def populate(self): - - device = get_device(self.module) - facts = dict(device.facts) - - if '2RE' in facts: - facts['has_2RE'] = facts['2RE'] - del facts['2RE'] - - facts['version_info'] = dict(facts['version_info']) - if 'junos_info' in facts: - for key, value in facts['junos_info'].items(): - if 'object' in value: - value['object'] = dict(value['object']) - - return facts diff --git a/lib/ansible/module_utils/network/junos/facts/lldp_global/lldp_global.py b/lib/ansible/module_utils/network/junos/facts/lldp_global/lldp_global.py deleted file mode 100644 index d6d4927813..0000000000 --- a/lib/ansible/module_utils/network/junos/facts/lldp_global/lldp_global.py +++ /dev/null @@ -1,89 +0,0 @@ -# -# -*- coding: utf-8 -*- -# Copyright 2019 Red Hat -# GNU General Public License v3.0+ -# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -""" -The junos lldp fact class -It is in this file the configuration is collected from the device -for a given resource, parsed, and the facts tree is populated -based on the configuration. -""" -from __future__ import absolute_import, division, print_function -__metaclass__ = type - -from copy import deepcopy - -from ansible.module_utils._text import to_bytes -from ansible.module_utils.network.common import utils -from ansible.module_utils.network.junos.argspec.lldp_global.lldp_global import Lldp_globalArgs -from ansible.module_utils.network.junos.utils.utils import get_resource_config -from ansible.module_utils.six import string_types -try: - from lxml import etree - HAS_LXML = True -except ImportError: - HAS_LXML = False - - -class Lldp_globalFacts(object): - """ The junos lldp fact class - """ - - def __init__(self, module, subspec='config', options='options'): - self._module = module - self.argument_spec = Lldp_globalArgs.argument_spec - spec = deepcopy(self.argument_spec) - if subspec: - if options: - facts_argument_spec = spec[subspec][options] - else: - facts_argument_spec = spec[subspec] - else: - facts_argument_spec = spec - - self.generated_spec = utils.generate_dict(facts_argument_spec) - - def populate_facts(self, connection, ansible_facts, data=None): - """ Populate the facts for interfaces - :param connection: the device connection - :param data: previously collected configuration as lxml ElementTree root instance - or valid xml sting - :rtype: dictionary - :returns: facts - """ - if not HAS_LXML: - self._module.fail_json(msg='lxml is not installed.') - - if not data: - config_filter = """ - <configuration> - <protocols> - <lldp> - </lldp> - </protocols> - </configuration> - """ - data = get_resource_config(connection, config_filter=config_filter) - - if isinstance(data, string_types): - data = etree.fromstring(to_bytes(data, errors='surrogate_then_replace')) - - facts = {} - config = deepcopy(self.generated_spec) - resources = data.xpath('configuration/protocols/lldp') - if resources: - lldp_root = resources[0] - config['address'] = utils.get_xml_conf_arg(lldp_root, 'management-address') - config['interval'] = utils.get_xml_conf_arg(lldp_root, 'advertisement-interval') - config['transmit_delay'] = utils.get_xml_conf_arg(lldp_root, 'transmit-delay') - config['hold_multiplier'] = utils.get_xml_conf_arg(lldp_root, 'hold-multiplier') - if utils.get_xml_conf_arg(lldp_root, 'disable', data='tag'): - config['enable'] = False - - params = utils.validate_config(self.argument_spec, {'config': utils.remove_empties(config)}) - - facts['lldp_global'] = utils.remove_empties(params['config']) - ansible_facts['ansible_network_resources'].update(facts) - - return ansible_facts diff --git a/lib/ansible/module_utils/network/junos/facts/lldp_interfaces/lldp_interfaces.py b/lib/ansible/module_utils/network/junos/facts/lldp_interfaces/lldp_interfaces.py deleted file mode 100644 index ec999010ed..0000000000 --- a/lib/ansible/module_utils/network/junos/facts/lldp_interfaces/lldp_interfaces.py +++ /dev/null @@ -1,104 +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 junos 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 - -from copy import deepcopy - -from ansible.module_utils._text import to_bytes -from ansible.module_utils.network.common import utils -from ansible.module_utils.network.junos.argspec.lldp_interfaces.lldp_interfaces import Lldp_interfacesArgs -from ansible.module_utils.network.junos.utils.utils import get_resource_config -from ansible.module_utils.six import string_types -try: - from lxml import etree - HAS_LXML = True -except ImportError: - HAS_LXML = False - - -class Lldp_interfacesFacts(object): - """ The junos 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 interfaces - :param connection: the device connection - :param data: previously collected configuration as lxml ElementTree root instance - or valid xml sting - :rtype: dictionary - :returns: facts - """ - if not HAS_LXML: - self._module.fail_json(msg='lxml is not installed.') - - if not data: - config_filter = """ - <configuration> - <protocols> - <lldp> - <interface> - </interface> - </lldp> - </protocols> - </configuration> - """ - data = get_resource_config(connection, config_filter=config_filter) - - if isinstance(data, string_types): - data = etree.fromstring(to_bytes(data, errors='surrogate_then_replace')) - - self._resources = data.xpath('configuration/protocols/lldp/interface') - - objs = [] - for resource in self._resources: - if resource is not None: - obj = self.render_config(self.generated_spec, resource) - 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 ElementTree instance of configuration object - :rtype: dictionary - :returns: The generated config - """ - config = deepcopy(spec) - config['name'] = utils.get_xml_conf_arg(conf, 'name') - if utils.get_xml_conf_arg(conf, 'disable', data='tag'): - config['enabled'] = False - return utils.remove_empties(config) diff --git a/lib/ansible/module_utils/network/junos/facts/static_routes/static_routes.py b/lib/ansible/module_utils/network/junos/facts/static_routes/static_routes.py deleted file mode 100644 index 9f8019a716..0000000000 --- a/lib/ansible/module_utils/network/junos/facts/static_routes/static_routes.py +++ /dev/null @@ -1,152 +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 junos 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._text import to_bytes -from ansible.module_utils.network.common import utils -from ansible.module_utils.network.junos.argspec.static_routes.static_routes import Static_routesArgs -from ansible.module_utils.six import string_types -try: - from lxml import etree - HAS_LXML = True -except ImportError: - HAS_LXML = False -try: - import xmltodict - HAS_XMLTODICT = True -except ImportError: - HAS_XMLTODICT = False - - -class Static_routesFacts(object): - """ The junos 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 populate_facts(self, connection, ansible_facts, data=None): - """ Populate the facts for static_routes - :param connection: the device connection - :param ansible_facts: Facts dictionary - :param data: previously collected conf - :rtype: dictionary - :returns: facts - """ - if not HAS_LXML: - self._module.fail_json(msg='lxml is not installed.') - if not HAS_XMLTODICT: - self._module.fail_json(msg='xmltodict is not installed.') - - if not data: - config_filter = """ - <configuration> - <routing-instances/> - <routing-options/> - </configuration> - """ - data = connection.get_configuration(filter=config_filter) - - if isinstance(data, string_types): - data = etree.fromstring(to_bytes(data, - errors='surrogate_then_replace')) - - resources = data.xpath('configuration/routing-options') - vrf_resources = data.xpath('configuration/routing-instances') - resources.extend(vrf_resources) - - objs = [] - for resource in resources: - if resource is not None: - xml = self._get_xml_dict(resource) - obj = self.render_config(self.generated_spec, xml) - if obj: - objs.append(obj) - - facts = {} - if objs: - facts['static_routes'] = [] - params = utils.validate_config(self.argument_spec, - {'config': objs}) - for cfg in params['config']: - facts['static_routes'].append(utils.remove_empties(cfg)) - ansible_facts['ansible_network_resources'].update(facts) - return ansible_facts - - def _get_xml_dict(self, xml_root): - xml_dict = xmltodict.parse(etree.tostring(xml_root), dict_constructor=dict) - return xml_dict - - def _create_route_dict(self, afi, route_path): - routes_dict = {'afi': afi, - 'routes': []} - if isinstance(route_path, dict): - route_path = [route_path] - for route in route_path: - route_dict = {} - route_dict['dest'] = route['name'] - if route.get('metric'): - route_dict['metric'] = route['metric']['metric-value'] - route_dict['next_hop'] = [] - route_dict['next_hop'].append({'forward_router_address': route['next-hop']}) - routes_dict['routes'].append(route_dict) - return routes_dict - - 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) - routes = [] - config['address_families'] = [] - - if conf.get('routing-options'): - if conf['routing-options'].get('rib'): - if conf['routing-options'].get('rib').get('name') == 'inet6.0': - if conf['routing-options'].get('rib').get('static'): - route_path = conf['routing-options']['rib']['static'].get('route') - routes.append(self._create_route_dict('ipv6', route_path)) - if conf['routing-options'].get('static'): - route_path = conf['routing-options']['static'].get('route') - routes.append(self._create_route_dict('ipv4', route_path)) - - if conf.get('routing-instances'): - config['vrf'] = conf['routing-instances']['instance']['name'] - if conf['routing-instances'].get('instance').get('routing-options').get('rib').get('name') == config['vrf'] + '.inet6.0': - if conf['routing-instances']['instance']['routing-options']['rib'].get('static'): - route_path = conf['routing-instances']['instance']['routing-options']['rib']['static'].get('route') - routes.append(self._create_route_dict('ipv6', route_path)) - if conf['routing-instances'].get('instance').get('routing-options').get('static'): - route_path = conf['routing-instances']['instance']['routing-options']['static'].get('route') - routes.append(self._create_route_dict('ipv4', route_path)) - config['address_families'].extend(routes) - return utils.remove_empties(config) diff --git a/lib/ansible/module_utils/network/junos/facts/vlans/vlans.py b/lib/ansible/module_utils/network/junos/facts/vlans/vlans.py deleted file mode 100644 index 24c875d019..0000000000 --- a/lib/ansible/module_utils/network/junos/facts/vlans/vlans.py +++ /dev/null @@ -1,103 +0,0 @@ -# -# -*- coding: utf-8 -*- -# Copyright 2019 Red Hat -# GNU General Public License v3.0+ -# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -""" -The junos 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._text import to_bytes -from ansible.module_utils.network.common import utils -from ansible.module_utils.network.junos.argspec.vlans.vlans import VlansArgs -from ansible.module_utils.network.junos.utils.utils import get_resource_config -from ansible.module_utils.six import string_types -try: - from lxml import etree - HAS_LXML = True -except ImportError: - HAS_LXML = False - - -class VlansFacts(object): - """ The junos vlans fact class - """ - - def __init__(self, module, subspec='config', options='options'): - self._module = module - self.argument_spec = VlansArgs.argument_spec - spec = deepcopy(self.argument_spec) - if subspec: - if options: - facts_argument_spec = spec[subspec][options] - else: - facts_argument_spec = spec[subspec] - else: - facts_argument_spec = spec - - self.generated_spec = utils.generate_dict(facts_argument_spec) - - def populate_facts(self, connection, ansible_facts, data=None): - """ Populate the facts for vlans - :param connection: the device connection - :param ansible_facts: Facts dictionary - :param data: previously collected conf - :rtype: dictionary - :returns: facts - """ - if not HAS_LXML: - self._module.fail_json(msg='lxml is not installed.') - - if not data: - config_filter = """ - <configuration> - <vlans> - </vlans> - </configuration> - """ - data = get_resource_config(connection, config_filter=config_filter) - - if isinstance(data, string_types): - data = etree.fromstring(to_bytes(data, - errors='surrogate_then_replace')) - - resources = data.xpath('configuration/vlans/vlan') - - objs = [] - for resource in resources: - if resource is not None: - obj = self.render_config(self.generated_spec, resource) - if obj: - objs.append(obj) - facts = {} - if 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): - """ - Render config as dictionary structure and delete keys - from spec for null values - - :param spec: The facts tree, generated from the argspec - :param conf: The configuration - :rtype: dictionary - :returns: The generated config - """ - config = deepcopy(spec) - config['name'] = utils.get_xml_conf_arg(conf, 'name') - config['vlan_id'] = utils.get_xml_conf_arg(conf, 'vlan-id') - config['description'] = utils.get_xml_conf_arg(conf, 'description') - return utils.remove_empties(config) diff --git a/lib/ansible/module_utils/network/junos/junos.py b/lib/ansible/module_utils/network/junos/junos.py deleted file mode 100644 index 5e6804924a..0000000000 --- a/lib/ansible/module_utils/network/junos/junos.py +++ /dev/null @@ -1,465 +0,0 @@ -# -# (c) 2017 Red Hat, Inc. -# -# This file is part of Ansible -# -# Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Ansible. If not, see <http://www.gnu.org/licenses/>. -# -import collections -import json -from contextlib import contextmanager -from copy import deepcopy - -from ansible.module_utils.basic import env_fallback -from ansible.module_utils.connection import Connection, ConnectionError -from ansible.module_utils.network.common.netconf import NetconfConnection -from ansible.module_utils._text import to_text - -try: - from lxml.etree import Element, SubElement, tostring as xml_to_string - HAS_LXML = True -except ImportError: - from xml.etree.ElementTree import Element, SubElement, tostring as xml_to_string - HAS_LXML = False - -try: - from jnpr.junos import Device - from jnpr.junos.exception import ConnectError - HAS_PYEZ = True -except ImportError: - HAS_PYEZ = False - -ACTIONS = frozenset(['merge', 'override', 'replace', 'update', 'set']) -JSON_ACTIONS = frozenset(['merge', 'override', 'update']) -FORMATS = frozenset(['xml', 'text', 'json']) -CONFIG_FORMATS = frozenset(['xml', 'text', 'json', 'set']) - -junos_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'), - 'timeout': dict(type='int'), - 'transport': dict(default='netconf', choices=['cli', 'netconf']) -} -junos_argument_spec = { - 'provider': dict(type='dict', options=junos_provider_spec, removed_in_version=2.14), -} - - -def tostring(element, encoding='UTF-8'): - if HAS_LXML: - return xml_to_string(element, encoding='unicode') - else: - return to_text(xml_to_string(element, encoding), encoding=encoding) - - -def get_provider_argspec(): - return junos_provider_spec - - -def get_connection(module): - if hasattr(module, '_junos_connection'): - return module._junos_connection - - capabilities = get_capabilities(module) - network_api = capabilities.get('network_api') - if network_api == 'cliconf': - module._junos_connection = Connection(module._socket_path) - elif network_api == 'netconf': - module._junos_connection = NetconfConnection(module._socket_path) - else: - module.fail_json(msg='Invalid connection type %s' % network_api) - - return module._junos_connection - - -def get_capabilities(module): - if hasattr(module, '_junos_capabilities'): - return module._junos_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._junos_capabilities = json.loads(capabilities) - return module._junos_capabilities - - -def get_device(module): - provider = module.params.get("provider") or {} - host = provider.get('host') - - kwargs = { - 'port': provider.get('port') or 830, - 'user': provider.get('username') - } - - if 'password' in provider: - kwargs['passwd'] = provider.get('password') - - if 'ssh_keyfile' in provider: - kwargs['ssh_private_key_file'] = provider.get('ssh_keyfile') - - if module.params.get('ssh_config'): - kwargs['ssh_config'] = module.params['ssh_config'] - - if module.params.get('ssh_private_key_file'): - kwargs['ssh_private_key_file'] = module.params['ssh_private_key_file'] - - kwargs['gather_facts'] = False - - try: - device = Device(host, **kwargs) - device.open() - device.timeout = provider.get('timeout') or 10 - except ConnectError as exc: - module.fail_json('unable to connect to %s: %s' % (host, to_text(exc))) - - return device - - -def is_netconf(module): - capabilities = get_capabilities(module) - return True if capabilities.get('network_api') == 'netconf' else False - - -def _validate_rollback_id(module, value): - try: - if not 0 <= int(value) <= 49: - raise ValueError - except ValueError: - module.fail_json(msg='rollback must be between 0 and 49') - - -def load_configuration(module, candidate=None, action='merge', rollback=None, format='xml'): - - if all((candidate is None, rollback is None)): - module.fail_json(msg='one of candidate or rollback must be specified') - - elif all((candidate is not None, rollback is not None)): - module.fail_json(msg='candidate and rollback are mutually exclusive') - - if format not in FORMATS: - module.fail_json(msg='invalid format specified') - - if format == 'json' and action not in JSON_ACTIONS: - module.fail_json(msg='invalid action for format json') - elif format in ('text', 'xml') and action not in ACTIONS: - module.fail_json(msg='invalid action format %s' % format) - if action == 'set' and format != 'text': - module.fail_json(msg='format must be text when action is set') - - conn = get_connection(module) - try: - if rollback is not None: - _validate_rollback_id(module, rollback) - obj = Element('load-configuration', {'rollback': str(rollback)}) - conn.execute_rpc(tostring(obj)) - else: - return conn.load_configuration(config=candidate, action=action, format=format) - except ConnectionError as exc: - module.fail_json(msg=to_text(exc, errors='surrogate_then_replace')) - - -def get_configuration(module, compare=False, format='xml', rollback='0', filter=None): - if format not in CONFIG_FORMATS: - module.fail_json(msg='invalid config format specified') - - conn = get_connection(module) - try: - if compare: - xattrs = {'format': format} - _validate_rollback_id(module, rollback) - xattrs['compare'] = 'rollback' - xattrs['rollback'] = str(rollback) - reply = conn.execute_rpc(tostring(Element('get-configuration', xattrs))) - else: - reply = conn.get_configuration(format=format, filter=filter) - except ConnectionError as exc: - module.fail_json(msg=to_text(exc, errors='surrogate_then_replace')) - return reply - - -def commit_configuration(module, confirm=False, check=False, comment=None, confirm_timeout=None, synchronize=False, at_time=None): - conn = get_connection(module) - try: - if check: - reply = conn.validate() - else: - if is_netconf(module): - reply = conn.commit(confirmed=confirm, timeout=confirm_timeout, comment=comment, synchronize=synchronize, at_time=at_time) - else: - reply = conn.commit(comment=comment, confirmed=confirm, at_time=at_time, synchronize=synchronize) - except ConnectionError as exc: - module.fail_json(msg=to_text(exc, errors='surrogate_then_replace')) - return reply - - -def command(module, cmd, format='text', rpc_only=False): - conn = get_connection(module) - if rpc_only: - cmd += ' | display xml rpc' - try: - response = conn.command(command=cmd, format=format) - except ConnectionError as exc: - module.fail_json(msg=to_text(exc, errors='surrogate_then_replace')) - return response - - -def lock_configuration(module): - conn = get_connection(module) - try: - response = conn.lock() - except ConnectionError as exc: - module.fail_json(msg=to_text(exc, errors='surrogate_then_replace')) - return response - - -def unlock_configuration(module): - conn = get_connection(module) - try: - response = conn.unlock() - except ConnectionError as exc: - module.fail_json(msg=to_text(exc, errors='surrogate_then_replace')) - return response - - -@contextmanager -def locked_config(module): - try: - lock_configuration(module) - yield - finally: - unlock_configuration(module) - - -def discard_changes(module): - conn = get_connection(module) - try: - response = conn.discard_changes() - except ConnectionError as exc: - module.fail_json(msg=to_text(exc, errors='surrogate_then_replace')) - return response - - -def get_diff(module, rollback='0'): - reply = get_configuration(module, compare=True, format='text', rollback=rollback) - # if warning is received from device diff is empty. - if isinstance(reply, list): - return None - - output = reply.find('.//configuration-output') - if output is not None: - return to_text(output.text, encoding='latin-1').strip() - - -def load_config(module, candidate, warnings, action='merge', format='xml'): - get_connection(module) - if not candidate: - return - - if isinstance(candidate, list): - candidate = '\n'.join(candidate) - - reply = load_configuration(module, candidate, action=action, format=format) - if isinstance(reply, list): - warnings.extend(reply) - - module._junos_connection.validate() - return get_diff(module) - - -def map_params_to_obj(module, param_to_xpath_map, param=None): - """ - Creates a new dictionary with key as xpath corresponding - to param and value is a list of dict with metadata and values for - the xpath. - Acceptable metadata keys: - 'value': Value of param. - 'tag_only': Value is indicated by tag only in xml hierarchy. - 'leaf_only': If operation is to be added at leaf node only. - 'value_req': If value(text) is required for leaf node. - 'is_key': If the field is key or not. - eg: Output - { - 'name': [{'value': 'ge-0/0/1'}] - 'disable': [{'value': True, tag_only': True}] - } - - :param module: - :param param_to_xpath_map: Modules params to xpath map - :return: obj - """ - if not param: - param = module.params - - obj = collections.OrderedDict() - for key, attribute in param_to_xpath_map.items(): - if key in param: - is_attribute_dict = False - - value = param[key] - if not isinstance(value, (list, tuple)): - value = [value] - - if isinstance(attribute, dict): - xpath = attribute.get('xpath') - is_attribute_dict = True - else: - xpath = attribute - - if not obj.get(xpath): - obj[xpath] = list() - - for val in value: - if is_attribute_dict: - attr = deepcopy(attribute) - del attr['xpath'] - - attr.update({'value': val}) - obj[xpath].append(attr) - else: - obj[xpath].append({'value': val}) - return obj - - -def map_obj_to_ele(module, want, top, value_map=None, param=None): - if not HAS_LXML: - module.fail_json(msg='lxml is not installed.') - - if not param: - param = module.params - - root = Element('root') - top_ele = top.split('/') - ele = SubElement(root, top_ele[0]) - - if len(top_ele) > 1: - for item in top_ele[1:-1]: - ele = SubElement(ele, item) - container = ele - state = param.get('state') - active = param.get('active') - if active: - oper = 'active' - else: - oper = 'inactive' - - # build xml subtree - if container.tag != top_ele[-1]: - node = SubElement(container, top_ele[-1]) - else: - node = container - - for fxpath, attributes in want.items(): - for attr in attributes: - tag_only = attr.get('tag_only', False) - leaf_only = attr.get('leaf_only', False) - value_req = attr.get('value_req', False) - is_key = attr.get('is_key', False) - parent_attrib = attr.get('parent_attrib', True) - value = attr.get('value') - field_top = attr.get('top') - - # operation 'delete' is added as element attribute - # only if it is key or leaf only node - if state == 'absent' and not (is_key or leaf_only): - continue - - # convert param value to device specific value - if value_map and fxpath in value_map: - value = value_map[fxpath].get(value) - - if (value is not None) or tag_only or leaf_only: - ele = node - if field_top: - # eg: top = 'system/syslog/file' - # field_top = 'system/syslog/file/contents' - # <file> - # <name>test</name> - # <contents> - # </contents> - # </file> - ele_list = root.xpath(top + '/' + field_top) - - if not len(ele_list): - fields = field_top.split('/') - ele = node - for item in fields: - inner_ele = root.xpath(top + '/' + item) - if len(inner_ele): - ele = inner_ele[0] - else: - ele = SubElement(ele, item) - else: - ele = ele_list[0] - - if value is not None and not isinstance(value, bool): - value = to_text(value, errors='surrogate_then_replace') - - if fxpath: - tags = fxpath.split('/') - for item in tags: - ele = SubElement(ele, item) - - if tag_only: - if state == 'present': - if not value: - # if value of tag_only node is false, delete the node - ele.set('delete', 'delete') - - elif leaf_only: - if state == 'present': - ele.set(oper, oper) - ele.text = value - else: - ele.set('delete', 'delete') - # Add value of leaf node if required while deleting. - # in some cases if value is present while deleting, it - # can result in error, hence the check - if value_req: - ele.text = value - if is_key: - par = ele.getparent() - par.set('delete', 'delete') - else: - ele.text = value - par = ele.getparent() - - if parent_attrib: - if state == 'present': - # set replace attribute at parent node - if not par.attrib.get('replace'): - par.set('replace', 'replace') - - # set active/inactive at parent node - if not par.attrib.get(oper): - par.set(oper, oper) - else: - par.set('delete', 'delete') - - return root.getchildren()[0] - - -def to_param_list(module): - aggregate = module.params.get('aggregate') - if aggregate: - if isinstance(aggregate, dict): - return [aggregate] - else: - return aggregate - else: - return [module.params] diff --git a/lib/ansible/module_utils/network/junos/utils/utils.py b/lib/ansible/module_utils/network/junos/utils/utils.py deleted file mode 100644 index 0d63c7a4b0..0000000000 --- a/lib/ansible/module_utils/network/junos/utils/utils.py +++ /dev/null @@ -1,28 +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 - -from ansible.module_utils.network.junos.junos import tostring -try: - from ncclient.xml_ import new_ele, to_ele - HAS_NCCLIENT = True -except ImportError: - HAS_NCCLIENT = False - - -def get_resource_config(connection, config_filter=None, attrib=None): - - if attrib is None: - attrib = {'inherit': 'inherit'} - - get_ele = new_ele('get-configuration', attrib) - if config_filter: - get_ele.append(to_ele(config_filter)) - - return connection.execute_rpc(tostring(get_ele)) |