From 3b64369d9b30b6946de52bcaedadee01e2803390 Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Sun, 26 May 2019 16:18:54 +0530 Subject: [PATCH 01/44] iosxr l2 interface Signed-off-by: Sumit Jaiswal --- library/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 library/__init__.py diff --git a/library/__init__.py b/library/__init__.py new file mode 100644 index 0000000..e69de29 From cd6de5b4775a0bf0a047b908c4436ecca5bc01e4 Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Sun, 26 May 2019 16:19:04 +0530 Subject: [PATCH 02/44] iosxr l2 interface Signed-off-by: Sumit Jaiswal --- library/iosxr_facts.py | 116 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 library/iosxr_facts.py diff --git a/library/iosxr_facts.py b/library/iosxr_facts.py new file mode 100644 index 0000000..4387577 --- /dev/null +++ b/library/iosxr_facts.py @@ -0,0 +1,116 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# {{ rm['COPYRIGHT'] }} +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +""" +The module file for iosxr_facts +""" + +from __future__ import absolute_import, division, print_function + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'network'} + +NETWORK_OS = "iosxr" +RESOURCE = "facts" +COPYRIGHT = "Copyright 2019 Red Hat" + +DOCUMENTATION = """ +--- +module: iosxr_facts +version_added: 2.9 +short_description: Get facts about Cisco IOSXR devices. +description: + - Collects facts from network devices running the iosxr operating + system. This module places the facts gathered in the fact tree keyed by the + respective resource name. The facts module will always collect a + base set of facts from the device and can enable or disable + collection of additional facts. +author: [u'Sumit Jaiswal (@justjais)'] +notes: + - Tested against IOSXRv Version 6.1.3 on VIRL +options: + gather_subset: + description: + - When supplied, this argument will restrict the facts collected + to a given subset. Possible values for this argument include + all, min, hardware, config, legacy, and interfaces. Can specify a + list of values to include a larger subset. Values can also be used + with an initial C(M(!)) to specify that a specific subset should + not be collected. + required: false + default: 'all' + version_added: "2.2" + gather_network_resources: + description: + - When supplied, this argument will restrict the facts collected + to a given subset. Possible values for this argument include + all and the resources like interfaces, vlans etc. + Can specify a list of values to include a larger subset. Values + can also be used with an initial C(M(!)) to specify that a + specific subset should not be collected. + required: false + version_added: "2.9" +""" + +EXAMPLES = """ +# Gather all facts +- iosxr_facts: + gather_subset: all + gather_network_resources: all + +# Collect only the iosxr facts +- iosxr_facts: + gather_subset: + - !all + - !min + gather_network_resources: + - iosxr + +# Do not collect iosxr facts +- iosxr_facts: + gather_network_resources: + - "!iosxr" + +# Collect iosxr and minimal default facts +- iosxr_facts: + gather_subset: min + gather_network_resources: iosxr +""" + +RETURN = """ +See the respective resource module parameters for the tree. +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.connection import Connection +from ansible.module_utils.ios.facts.facts import Facts + +def main(): + """ + Main entry point for module execution + + :returns: ansible_facts + """ + module = AnsibleModule(argument_spec=Facts.argument_spec, + supports_check_mode=True) + warnings = ['default value for `gather_subset` will be changed to `min` from `!config` v2.11 onwards'] + + connection = Connection(module._socket_path) + gather_subset = module.params['gather_subset'] + gather_network_resources = module.params['gather_network_resources'] + result = Facts().get_facts(module, connection, gather_subset, gather_network_resources) + + try: + ansible_facts, warning = result + warnings.extend(warning) + except (TypeError, KeyError): + ansible_facts = result + + module.exit_json(ansible_facts=ansible_facts, warnings=warnings) + + +if __name__ == '__main__': + main() + From b48b5563830651d2704e21691537c32cc37aff33 Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Sun, 26 May 2019 16:19:14 +0530 Subject: [PATCH 03/44] iosxr l2 interface Signed-off-by: Sumit Jaiswal --- library/iosxr_l2_interface.py | 384 ++++++++++++++++++++++++++++++++++ 1 file changed, 384 insertions(+) create mode 100644 library/iosxr_l2_interface.py diff --git a/library/iosxr_l2_interface.py b/library/iosxr_l2_interface.py new file mode 100644 index 0000000..439cf3a --- /dev/null +++ b/library/iosxr_l2_interface.py @@ -0,0 +1,384 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# {{ rm['COPYRIGHT'] }} +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +############################################## +################# WARNING #################### +############################################## +### +### This file is auto generated by the resource +### module builder playbook. +### +### Do not edit this file manually. +### +### Changes to this file will be over written +### by the resource module builder. +### +### Changes should be made in the model used to +### generate this file or in the resource module +### builder template. +### +############################################## +############################################## +############################################## + +""" +The module file for iosxr_l2_interfaces +""" + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +#{{ rm|to_doc(model) }} + +GENERATOR_VERSION = '1.0' + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'network'} + +NETWORK_OS = "iosxr" +RESOURCE = "l2_interfaces" +COPYRIGHT = "Copyright 2019 Red Hat" + +DOCUMENTATION = """ +--- + module: iosxr_l2_interfaces + version_added: 2.9 + short_description: Manage Layer-2 interface on Cisco IOS-XR devices. + description: This module provides declarative management of Layer-2 interface on Cisco IOS-XR devices. + author: Sumit Jaiswal (@justjais) + options: + config: + description: A dictionary of Layer-2 interface options + type: list + elements: dict + suboptions: + name: + description: + - Full name of the interface/sub-interface excluding any logical unit number, + i.e. GigabitEthernet0/0/0/1 or GigabitEthernet0/0/0/1.100. + type: str + required: True + native_vlan: + description: + - Configure a native VLAN ID for the trunk + type: str + l2transport: + description: + - Switchport mode access command to configure the interface as a layer 2 access. + type: bool + l2protocol: + description: + - Configures Layer 2 protocol tunneling and protocol data unit (PDU) filtering on an interface. + suboptions: + cdp: + description: + - Cisco Discovery Protocol (CDP) tunneling and data unit parameters. + choices: ['drop','forward', 'tunnel'] + type: str + pvst: + description: + - Configures VLAN spanning tree protocol tunneling and data unit parameters. + choices: ['drop','forward', 'tunnel'] + type: str + stp: + description: + - Spanning tree protocol tunneling and data unit parameters. + choices: ['drop','forward', 'tunnel'] + type: str + vtp: + description: + - VLAN trunk protocol tunneling and data unit parameters. + choices: ['drop','forward', 'tunnel'] + type: str + q_vlan: + description: + - 802.1Q VLAN configuration. Note that it can accept either 2 VLAN IDs when configuring Q-in-Q vlan, + or it shall accept 1 VLAN ID and 'any' as input list when configuring Q-in-any vlan as input. + type: str + propagate: + description: + - Propagate Layer 2 transport events. Note that it will work only when l2tranport param is set + to True. + type: bool + state: + choices: + - merged + - replaced + - overridden + - deleted + default: merged + description: + - The state the configuration should be left in + type: str +""" + + +EXAMPLES = """ +--- + +# Using merged + +# Before state: +# ------------- +# +# viosxr#show running-config interface +# interface GigabitEthernet0/0/0/3 +# description Ansible Network +# vrf custB +# ipv4 address 10.10.0.2 255.255.255.0 +# duplex half +# shutdown +# ! +# interface GigabitEthernet0/0/0/4 +# description Test description +# ! + +- name: Merge provided configuration with device configuration + iosxr_l2_interfaces: + config: + - name: GigabitEthernet0/0/0/3 + native_vlan: 20 + - name: GigabitEthernet0/0/0/4 + native_vlan: 40 + l2transport: True + l2protocol: + - stp: tunnel + - name: GigabitEthernet0/0/0/3.900 + l2transport: True + q_vlan: + - 20 + - 40 + state: merged + +# After state: +# ------------ +# +# viosxr#show running-config interface +# interface GigabitEthernet0/0/0/3 +# description Ansible Network +# vrf custB +# ipv4 address 10.10.0.2 255.255.255.0 +# duplex half +# shutdown +# dot1q native vlan 20 +# ! +# interface GigabitEthernet0/0/0/4 +# description Test description +# dot1q native vlan 10 +# l2transport +# l2protocol stp tunnel +# ! +# ! +# interface GigabitEthernet0/0/0/3.900 l2transport +# dot1q vlan 20 40 +# ! + +# Using replaced + +# Before state: +# ------------- +# +# viosxr#show running-config interface +# interface GigabitEthernet0/0/0/3 +# description Ansible Network +# vrf custB +# ipv4 address 10.10.0.2 255.255.255.0 +# duplex half +# shutdown +# dot1q native vlan 20 +# ! +# interface GigabitEthernet0/0/0/4 +# description Test description +# dot1q native vlan 10 +# l2transport +# l2protocol stp tunnel +# ! +# ! +# interface GigabitEthernet0/0/0/3.900 l2transport +# dot1q vlan 20 40 +# ! + +- name: Replaces device configuration of listed interfaces with provided configuration + iosxr_interfaces: + config: + - name: GigabitEthernet0/0/0/4 + native_vlan: 40 + l2transport: True + l2protocol: + - stp: forward + - name: GigabitEthernet0/0/0/3.900 + q_vlan: + - 20 + - any + state: overridden + +# After state: +# ------------- +# +# viosxr#show running-config interface +# interface GigabitEthernet0/0/0/3 +# description Ansible Network +# vrf custB +# ipv4 address 10.10.0.2 255.255.255.0 +# duplex half +# shutdown +# dot1q native vlan 20 +# ! +# interface GigabitEthernet0/0/0/4 +# description Test description +# dot1q native vlan 40 +# l2transport +# l2protocol stp forward +# ! +# ! +# interface GigabitEthernet0/0/0/3.900 l2transport +# dot1q vlan 20 any +# ! + +# Using overridden + +# Before state: +# ------------- +# +# viosxr#show running-config interface +# interface GigabitEthernet0/0/0/3 +# description Ansible Network +# vrf custB +# ipv4 address 10.10.0.2 255.255.255.0 +# duplex half +# shutdown +# dot1q native vlan 20 +# ! +# interface GigabitEthernet0/0/0/4 +# description Test description +# dot1q native vlan 10 +# l2transport +# l2protocol stp tunnel +# ! +# ! +# interface GigabitEthernet0/0/0/3.900 l2transport +# dot1q vlan 20 40 +# ! + +- name: Override device configuration of all interfaces with provided configuration + iosxr_interfaces: + config: + - name: GigabitEthernet0/0/0/4 + native_vlan: 40 + l2transport: True + l2protocol: + - stp: forward + - name: GigabitEthernet0/0/0/3.900 + q_vlan: + - 20 + - any + state: overridden + +# After state: +# ------------- +# +# viosxr#show running-config interface +# interface GigabitEthernet0/0/0/3 +# description Ansible Network +# vrf custB +# ipv4 address 10.10.0.2 255.255.255.0 +# duplex half +# shutdown +# ! +# interface GigabitEthernet0/0/0/4 +# description Test description +# dot1q native vlan 40 +# l2transport +# l2protocol stp forward +# ! +# ! +# interface GigabitEthernet0/0/0/3.900 +# dot1q vlan 20 any +# ! + +# Using deleted + +# Before state: +# ------------- +# +# viosxr#show running-config interface +# interface GigabitEthernet0/0/0/3 +# description Ansible Network +# vrf custB +# ipv4 address 10.10.0.2 255.255.255.0 +# duplex half +# shutdown +# dot1q native vlan 20 +# ! +# interface GigabitEthernet0/0/0/4 +# description Test description +# dot1q native vlan 10 +# l2transport +# l2protocol stp tunnel +# ! +# ! + +- name: Delete attributes of given interfaces (Note: This won't delete the interface itself) + iosxr_l2_interfaces: + config: + - name: GigabitEthernet0/0/0/3 + - name: GigabitEthernet0/0/0/4 + state: deleted + +# After state: +# ------------ +# +# viosxr#show running-config interface +# interface GigabitEthernet0/0/0/3 +# description Ansible Network +# vrf custB +# ipv4 address 10.10.0.2 255.255.255.0 +# duplex half +# shutdown +# ! +# interface GigabitEthernet0/0/0/4 +# description Test description +# ! + +""" + +RETURN = """ +before: + description: The configuration prior to the model invocation + returned: always + sample: The configuration returned will alwys be in the same format of the paramters above. +after: + description: The resulting configuration model invocation + returned: when changed + sample: The configuration returned will alwys be in the same format of the paramters above. +commands: + description: The set of commands pushed to the remote device + returned: always + type: list + sample: ['command 1', 'command 2', 'command 3'] +""" + + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.iosxr.config.l2_interfaces.l2_interfaces import L2_Interfaces + + +def main(): + """ + Main entry point for module execution + + :returns: the result form module invocation + """ + module = AnsibleModule(argument_spec=L2_Interfaces.argument_spec, + supports_check_mode=True) + + result = L2_Interfaces(module).execute_module() + module.exit_json(**result) + + +if __name__ == '__main__': + main() + From 8f6167478f358577a33e1ead801077132f05b09d Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Sun, 26 May 2019 16:19:25 +0530 Subject: [PATCH 04/44] iosxr l2 interface Signed-off-by: Sumit Jaiswal --- module_utils/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 module_utils/__init__.py diff --git a/module_utils/__init__.py b/module_utils/__init__.py new file mode 100644 index 0000000..e69de29 From 20d480b1bd8de660336f5f86139e8b25c6879003 Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Sun, 26 May 2019 16:19:36 +0530 Subject: [PATCH 05/44] iosxr l2 interface Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 module_utils/iosxr/__init__.py diff --git a/module_utils/iosxr/__init__.py b/module_utils/iosxr/__init__.py new file mode 100644 index 0000000..e69de29 From 41f969e9007768d4e7707e18830fb09269fadd52 Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Sun, 26 May 2019 16:19:50 +0530 Subject: [PATCH 06/44] iosxr l2 interface Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/argspec/__init__.py | 1 + 1 file changed, 1 insertion(+) create mode 100644 module_utils/iosxr/argspec/__init__.py diff --git a/module_utils/iosxr/argspec/__init__.py b/module_utils/iosxr/argspec/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/module_utils/iosxr/argspec/__init__.py @@ -0,0 +1 @@ + From 6fb2152fc7efb93f6a51a8ddd502d29d2fe309ac Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Sun, 26 May 2019 16:37:32 +0530 Subject: [PATCH 07/44] iosxr l2 interface Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/argspec/facts/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 module_utils/iosxr/argspec/facts/__init__.py diff --git a/module_utils/iosxr/argspec/facts/__init__.py b/module_utils/iosxr/argspec/facts/__init__.py new file mode 100644 index 0000000..e69de29 From 2e27d3a8ea2c60a5721c57506b22b9f7d9ee47cf Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Sun, 26 May 2019 16:37:32 +0530 Subject: [PATCH 08/44] iosxr l2 interface Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/argspec/facts/facts.py | 24 +++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 module_utils/iosxr/argspec/facts/facts.py diff --git a/module_utils/iosxr/argspec/facts/facts.py b/module_utils/iosxr/argspec/facts/facts.py new file mode 100644 index 0000000..88d8755 --- /dev/null +++ b/module_utils/iosxr/argspec/facts/facts.py @@ -0,0 +1,24 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# {{ rm['COPYRIGHT'] }} +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +""" +The arg spec for the iosxr facts module. +""" + +class FactsArgs(object): #pylint: disable=R0903 + """ The arg spec for the iosxr facts module + """ + + def __init__(self, **kwargs): + pass + + choices = [ + 'all', + 'l2_interfaces', + ] + + argument_spec = { + 'gather_subset': dict(default=['!config'], type='list'), + 'gather_network_resources': dict(default=['all'], choices=choices, type='list'), + } From e8d1f0b482f8828de51bb6a3d84694e5527ebd0f Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Sun, 26 May 2019 16:37:32 +0530 Subject: [PATCH 09/44] iosxr l2 interface Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/argspec/l2_interfaces/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 module_utils/iosxr/argspec/l2_interfaces/__init__.py diff --git a/module_utils/iosxr/argspec/l2_interfaces/__init__.py b/module_utils/iosxr/argspec/l2_interfaces/__init__.py new file mode 100644 index 0000000..e69de29 From 9ad68f4923d99feb5b86cdb150352f0f47ca1fdb Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Sun, 26 May 2019 16:37:32 +0530 Subject: [PATCH 10/44] iosxr l2 interface Signed-off-by: Sumit Jaiswal --- .../argspec/l2_interfaces/l2_interfaces.py | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 module_utils/iosxr/argspec/l2_interfaces/l2_interfaces.py diff --git a/module_utils/iosxr/argspec/l2_interfaces/l2_interfaces.py b/module_utils/iosxr/argspec/l2_interfaces/l2_interfaces.py new file mode 100644 index 0000000..138b55d --- /dev/null +++ b/module_utils/iosxr/argspec/l2_interfaces/l2_interfaces.py @@ -0,0 +1,51 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright 2019 Red Hat Inc. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +############################################# +################# WARNING #################### +############################################## +### +### This file is auto generated by the resource +### module builder playbook. +### +### Do not edit this file manually. +### +### Changes to this file will be over written +### by the resource module builder. +### +### Changes should be made in the model used to +### generate this file or in the resource module +### builder template. +### +############################################## +############################################## +############################################## +""" +The arg spec for the iosxr_l2_interfaces module +""" + +class L2_InterfacesArgs(object): + + def __init__(self, **kwargs): + pass + + l2_protocol_arg_spec = dict(cdp=dict(type=str, element=dict, choices=['drop','forward', 'tunnel']), + pvst=dict(type=str, element=dict, choices=['drop','forward', 'tunnel']), + stp=dict(type=str, element=dict, choices=['drop','forward', 'tunnel']), + vtp=dict(type=str, element=dict, choices=['drop','forward', 'tunnel']) + ) + + config_spec = { + 'name': dict(type='str', required=True), + 'native_vlan': dict(type=str), + 'l2transport': dict(element=dict, type=bool), + 'l2protocol': dict(element=dict, type=list, options=l2_protocol_arg_spec), + 'q_vlan':dict(element=dict, type=list), + } + + argument_spec = { + 'state': dict(default='merged', choices=['merged', 'replaced', 'overridden', 'deleted']), + 'config': dict(type='list', elements='dict', options=config_spec) + } From 517c730731f73a664ebd30bd2fffb22d7fd10eb1 Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Sun, 26 May 2019 16:37:32 +0530 Subject: [PATCH 11/44] iosxr l2 interface Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/argspec/resource/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 module_utils/iosxr/argspec/resource/__init__.py diff --git a/module_utils/iosxr/argspec/resource/__init__.py b/module_utils/iosxr/argspec/resource/__init__.py new file mode 100644 index 0000000..e69de29 From 277c1efbd8949876ba94768813217f1c2790d99d Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Sun, 26 May 2019 16:37:32 +0530 Subject: [PATCH 12/44] iosxr l2 interface Signed-off-by: Sumit Jaiswal --- .../iosxr/argspec/resource/resource.py | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 module_utils/iosxr/argspec/resource/resource.py diff --git a/module_utils/iosxr/argspec/resource/resource.py b/module_utils/iosxr/argspec/resource/resource.py new file mode 100644 index 0000000..3c343e7 --- /dev/null +++ b/module_utils/iosxr/argspec/resource/resource.py @@ -0,0 +1,27 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# {{ rm['COPYRIGHT'] }} +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +############################################# +################# WARNING #################### +############################################## +### +### This file is auto generated by the resource +### module builder playbook. +### +### Do not edit this file manually. +### +### Changes to this file will be over written +### by the resource module builder. +### +### Changes should be made in the model used to +### generate this file or in the resource module +### builder template. +### +############################################## +############################################## +############################################## +""" +The arg spec for the iosxr_l2_interfaces module +""" \ No newline at end of file From 9e0774610a240856fd30623102f4dc2a73154574 Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Sun, 26 May 2019 16:37:32 +0530 Subject: [PATCH 13/44] iosxr l2 interface Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/config/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 module_utils/iosxr/config/__init__.py diff --git a/module_utils/iosxr/config/__init__.py b/module_utils/iosxr/config/__init__.py new file mode 100644 index 0000000..e69de29 From ceb7a37280aa4b885a562f350a357862a2f57875 Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Sun, 26 May 2019 16:37:32 +0530 Subject: [PATCH 14/44] iosxr l2 interface Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/config/base.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 module_utils/iosxr/config/base.py diff --git a/module_utils/iosxr/config/base.py b/module_utils/iosxr/config/base.py new file mode 100644 index 0000000..99e9d1e --- /dev/null +++ b/module_utils/iosxr/config/base.py @@ -0,0 +1,24 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# {{ rm['COPYRIGHT'] }} +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +""" +The base class for all iosxr resource modules +""" + +from ansible.module_utils.connection import Connection + +class ConfigBase(object): #pylint: disable=R0205,R0903 + """ The base class for all iosxr resource modules + """ + _connection = None + + def __init__(self, module): + self._module = module + self._connection = self._get_connection() + + def _get_connection(self): + if self._connection: + return self._connection + self._connection = Connection(self._module._socket_path) #pylint: disable=W0212 + return self._connection From ac15454a49c403146648e428f95aec5f0c4f0b4c Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Sun, 26 May 2019 16:37:32 +0530 Subject: [PATCH 15/44] iosxr l2 interface Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/config/l2_interfaces/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 module_utils/iosxr/config/l2_interfaces/__init__.py diff --git a/module_utils/iosxr/config/l2_interfaces/__init__.py b/module_utils/iosxr/config/l2_interfaces/__init__.py new file mode 100644 index 0000000..e69de29 From a9382032fb88dc8720535cf41fe62e1e8eb429a4 Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Sun, 26 May 2019 16:37:32 +0530 Subject: [PATCH 16/44] iosxr l2 interface Signed-off-by: Sumit Jaiswal --- .../config/l2_interfaces/l2_interfaces.py | 159 ++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 module_utils/iosxr/config/l2_interfaces/l2_interfaces.py diff --git a/module_utils/iosxr/config/l2_interfaces/l2_interfaces.py b/module_utils/iosxr/config/l2_interfaces/l2_interfaces.py new file mode 100644 index 0000000..5c15910 --- /dev/null +++ b/module_utils/iosxr/config/l2_interfaces/l2_interfaces.py @@ -0,0 +1,159 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright 2019 Red Hat Inc. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +""" +The iosxr_l2_interfaces class +It is in this file where the current configuration (as dict) +is compared to the provided configuration (as dict) and the command set +necessary to bring the current configuration to it's desired end-state is +created +""" + +from ansible.module_utils.network.common.utils import to_list + +from ansible.module_utils.iosxr.argspec.l2_interfaces.l2_interfaces import L2_InterfacesArgs +from ansible.module_utils.iosxr.config.base import ConfigBase +from ansible.module_utils.iosxr.facts.facts import Facts +from ansible.module_utils.iosxr.utils.utils import get_interface_type, normalize_interface, search_obj_in_list +import q + +class L2_Interfaces(ConfigBase, L2_InterfacesArgs): + """ + The iosxr_l2_interfaces class + """ + + gather_subset = [ + '!all', + '!min', + ] + + gather_network_resources = [ + 'l2_interfaces', + ] + + def get_l2_interfaces_facts(self): + """ Get the 'facts' (the current configuration) + + :rtype: A dictionary + :returns: The current configuration as a dictionary + """ + result = Facts().get_facts(self._module, self._connection, self.gather_subset, self.gather_network_resources) + try: + facts = result[0] + q(facts) + except (TypeError, KeyError): + facts = result + l2_interfaces_facts = facts['ansible_network_resources'].get('l2_interfaces') + q(l2_interfaces_facts) + if not l2_interfaces_facts: + return [] + return l2_interfaces_facts + + def execute_module(self): + """ Execute the module + + :rtype: A dictionary + :returns: The result from module execution + """ + result = {'changed': False} + commands = list() + warnings = list() + + existing_l2_interfaces_facts = self.get_l2_interfaces_facts() + commands.extend(self.set_config(existing_l2_interfaces_facts)) + if commands: + if not self._module.check_mode: + self._connection.edit_config(commands) + result['changed'] = True + result['commands'] = commands + + changed_l2_interfaces_facts = self.get_l2_interfaces_facts() + + result['before'] = existing_l2_interfaces_facts + if result['changed']: + result['after'] = changed_l2_interfaces_facts + + result['warnings'] = warnings + return result + + def set_config(self, existing_l2_interfaces_facts): + """ Collect the configuration from the args passed to the module, + collect the current configuration (as a dict from facts) + + :rtype: A list + :returns: the commands necessary to migrate the current configuration + to the desired configuration + """ + want = self._module.params['config'] + have = existing_l2_interfaces_facts + resp = self.set_state(want, have) + return to_list(resp) + + def set_state(self, want, have): + """ Select the appropriate function based on the state provided + + :param want: the desired configuration as a dictionary + :param have: the current configuration as a dictionary + :rtype: A list + :returns: the commands necessary to migrate the current configuration + to the desired configuration + """ + state = self._module.params['state'] + if state == 'overridden': + kwargs = {} + commands = self._state_overridden(**kwargs) + elif state == 'deleted': + kwargs = {} + commands = self._state_deleted(**kwargs) + elif state == 'merged': + kwargs = {} + commands = self._state_merged(**kwargs) + elif state == 'replaced': + kwargs = {} + commands = self._state_replaced(**kwargs) + return commands + + @staticmethod + def _state_replaced(**kwargs): + """ The command generator when state is replaced + + :rtype: A list + :returns: the commands necessary to migrate the current configuration + to the desired configuration + """ + commands = [] + return commands + + @staticmethod + def _state_overridden(**kwargs): + """ The command generator when state is overridden + + :rtype: A list + :returns: the commands necessary to migrate the current configuration + to the desired configuration + """ + commands = [] + return commands + + @staticmethod + def _state_merged(**kwargs): + """ The command generator when state is merged + + :rtype: A list + :returns: the commands necessary to merge the provided into + the current configuration + """ + commands = [] + return commands + + @staticmethod + def _state_deleted(**kwargs): + """ The command generator when state is deleted + + :rtype: A list + :returns: the commands necessary to remove the current configuration + of the provided objects + """ + commands = [] + return commands \ No newline at end of file From 8570fdf1684a03cef930745849a171e952a05e69 Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Sun, 26 May 2019 16:37:32 +0530 Subject: [PATCH 17/44] iosxr l2 interface Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/config/resource/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 module_utils/iosxr/config/resource/__init__.py diff --git a/module_utils/iosxr/config/resource/__init__.py b/module_utils/iosxr/config/resource/__init__.py new file mode 100644 index 0000000..e69de29 From 14f5232fc82545698ab329ca914e1a2aa519aea5 Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Sun, 26 May 2019 16:37:32 +0530 Subject: [PATCH 18/44] iosxr l2 interface Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/config/resource/resource.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 module_utils/iosxr/config/resource/resource.py diff --git a/module_utils/iosxr/config/resource/resource.py b/module_utils/iosxr/config/resource/resource.py new file mode 100644 index 0000000..e69de29 From 3626913696f433b54c0c61a4a1bca7a29afd6780 Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Sun, 26 May 2019 16:37:32 +0530 Subject: [PATCH 19/44] iosxr l2 interface Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/facts/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 module_utils/iosxr/facts/__init__.py diff --git a/module_utils/iosxr/facts/__init__.py b/module_utils/iosxr/facts/__init__.py new file mode 100644 index 0000000..e69de29 From dd6b49c635046cb7718e7b1d2e02834abad273b3 Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Sun, 26 May 2019 16:37:32 +0530 Subject: [PATCH 20/44] iosxr l2 interface Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/facts/base.py | 110 +++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 module_utils/iosxr/facts/base.py diff --git a/module_utils/iosxr/facts/base.py b/module_utils/iosxr/facts/base.py new file mode 100644 index 0000000..5c36d83 --- /dev/null +++ b/module_utils/iosxr/facts/base.py @@ -0,0 +1,110 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# {{ rm['COPYRIGHT'] }} +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +""" +The iosxr facts base class +this contains methods common to all facts subsets +""" + +import re +from copy import deepcopy +from ansible.module_utils.six import iteritems + + +class FactsBase(object): #pylint: disable=R0205 + """ + The iosxr facts base class + """ + generated_spec = {} + ansible_facts = {'ansible_network_resources': {}} + + def __init__(self, argspec, subspec=None, options=None): + spec = deepcopy(argspec) + if subspec: + if options: + facts_argument_spec = spec[subspec][options] + else: + facts_argument_spec = spec[subspec] + else: + facts_argument_spec = spec + + self.generated_spec = self.generate_dict(facts_argument_spec) + + @staticmethod + def generate_dict(spec): + """ + Generate dictionary which is in sync with argspec + + :param spec: A dictionary which the argspec of module + :rtype: A dictionary + :returns: A dictionary in sync with argspec with default value + """ + obj = {} + if not spec: + return obj + + for key, val in iteritems(spec): + if 'default' in val: + dct = {key: val['default']} + else: + dct = {key: None} + obj.update(dct) + + return obj + + @staticmethod + def parse_conf_arg(cfg, arg): + """ + Parse config based on argument + + :param cfg: A text string which is a line of configuration. + :param arg: A text string which is to be matched. + :rtype: A text string + :returns: A text string if match is found + """ + match = re.search(r'%s (.+)(\n|$)' % arg, cfg, re.M) + if match: + result = match.group(1).strip() + else: + result = None + return result + + @staticmethod + def parse_conf_cmd_arg(cfg, cmd, res1, res2=None): + """ + Parse config based on command + + :param cfg: A text string which is a line of configuration. + :param cmd: A text string which is the command to be matched + :param res1: A text string to be returned if the command is present + :param res2: A text string to be returned if the negate command is present + :rtype: A text string + :returns: A text string if match is found + """ + match = re.search(r'\n\s+%s(\n|$)' % cmd, cfg) + if match: + return res1 + if res2 is not None: + match = re.search(r'\n\s+no %s(\n|$)' % cmd, cfg) + if match: + return res2 + return None + + @staticmethod + def generate_final_config(cfg_dict): + """ + Generate final config dictionary + + :param cfg_dict: A dictionary parsed in the facts system + :rtype: A dictionary + :returns: A dictionary by eliminating keys that have null values + """ + final_cfg = {} + if not cfg_dict: + return final_cfg + + for key, val in iteritems(cfg_dict): + if val: + final_cfg.update({key:val}) + return final_cfg \ No newline at end of file From c57b239f2c86d9be334ee0aef3c153e7a2b2b4db Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Sun, 26 May 2019 16:37:32 +0530 Subject: [PATCH 21/44] iosxr l2 interface Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/facts/facts.py | 121 ++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 module_utils/iosxr/facts/facts.py diff --git a/module_utils/iosxr/facts/facts.py b/module_utils/iosxr/facts/facts.py new file mode 100644 index 0000000..8d980f6 --- /dev/null +++ b/module_utils/iosxr/facts/facts.py @@ -0,0 +1,121 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# {{ rm['COPYRIGHT'] }} +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +""" +The facts class for iosxr +this file validates each subset of facts and selectively +calls the appropriate facts gathering function +""" + + +from ansible.module_utils.six import iteritems + +from ansible.module_utils.iosxr.argspec.facts.facts import FactsArgs +from ansible.module_utils.iosxr.facts.base import FactsBase +from ansible.module_utils.iosxr.argspec.l2_interfaces.l2_interfaces import L2_InterfacesArgs +from ansible.module_utils.iosxr.facts.l2_interfaces.l2_interfaces import InterfacesFacts +import q + +FACT_SUBSETS = {} + +class Facts(FactsArgs, FactsBase): #pylint: disable=R0903 + """ The fact class for iosxr + """ + + VALID_GATHER_SUBSETS = frozenset(FACT_SUBSETS.keys()) + + def generate_runable_subsets(self, module, subsets, valid_subsets): + runable_subsets = set() + exclude_subsets = set() + minimal_gather_subset = frozenset(['default']) + + for subset in subsets: + if subset == 'all': + runable_subsets.update(valid_subsets) + continue + if subset == 'min' and minimal_gather_subset: + runable_subsets.update(minimal_gather_subset) + continue + if subset.startswith('!'): + subset = subset[1:] + if subset == 'min': + exclude_subsets.update(minimal_gather_subset) + continue + if subset == 'all': + exclude_subsets.update(valid_subsets - minimal_gather_subset) + continue + exclude = True + else: + exclude = False + + if subset not in valid_subsets: + module.fail_json(msg='Bad subset') + + if exclude: + exclude_subsets.add(subset) + else: + runable_subsets.add(subset) + + if not runable_subsets: + runable_subsets.update(valid_subsets) + runable_subsets.difference_update(exclude_subsets) + + return runable_subsets + + def get_facts(self, module, connection, gather_subset=['!config'], gather_network_resources=['all']): + """ Collect the facts for iosxr + + :param module: The module instance + :param connection: The device connection + :param gather_subset: The facts subset to collect + :param gather_network_resources: The resource subset to collect + :rtype: dict + :returns: the facts gathered + """ + warnings = [] + self.ansible_facts['gather_network_resources'] = list() + self.ansible_facts['gather_subset'] = list() + + valid_network_resources_subsets = self.argument_spec['gather_network_resources'].get('choices', []) + if valid_network_resources_subsets and 'all' in valid_network_resources_subsets: + valid_network_resources_subsets.remove('all') + + if valid_network_resources_subsets: + resources_runable_subsets = self.generate_runable_subsets(module, gather_network_resources, valid_network_resources_subsets) + if resources_runable_subsets: + self.ansible_facts['gather_network_resources'] = list(resources_runable_subsets) + q(resources_runable_subsets) + for attr in resources_runable_subsets: + q(attr, module, connection) + getattr(self, '_get_%s' % attr, {})(module, connection) + + if self.VALID_GATHER_SUBSETS: + runable_subsets = self.generate_runable_subsets(module, gather_subset, self.VALID_GATHER_SUBSETS) + + if runable_subsets: + facts = dict() + self.ansible_facts['gather_subset'] = list(runable_subsets) + + instances = list() + for key in runable_subsets: + instances.append(FACT_SUBSETS[key](module)) + + for inst in instances: + inst.populate() + facts.update(inst.facts) + warnings.extend(inst.warnings) + + for key, value in iteritems(facts): + key = 'ansible_net_%s' % key + self.ansible_facts[key] = value + + if warnings: + return self.ansible_facts, warnings + else: + return self.ansible_facts + + + @staticmethod + def _get_net_configuration_interfaces(module, connection): + return InterfacesFacts(L2_InterfacesArgs.argument_spec, 'config', 'options').populate_facts(module, connection) \ No newline at end of file From 82849b9b969eab9ae7d496399fd41ee06ed29389 Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Sun, 26 May 2019 16:37:32 +0530 Subject: [PATCH 22/44] iosxr l2 interface Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/facts/l2_interfaces/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 module_utils/iosxr/facts/l2_interfaces/__init__.py diff --git a/module_utils/iosxr/facts/l2_interfaces/__init__.py b/module_utils/iosxr/facts/l2_interfaces/__init__.py new file mode 100644 index 0000000..e69de29 From a4fb5eb0203ae0d77419af4ef3b59b6788327b4a Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Sun, 26 May 2019 16:37:32 +0530 Subject: [PATCH 23/44] iosxr l2 interface Signed-off-by: Sumit Jaiswal --- .../facts/l2_interfaces/l2_interfaces.py | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 module_utils/iosxr/facts/l2_interfaces/l2_interfaces.py diff --git a/module_utils/iosxr/facts/l2_interfaces/l2_interfaces.py b/module_utils/iosxr/facts/l2_interfaces/l2_interfaces.py new file mode 100644 index 0000000..97b1ed7 --- /dev/null +++ b/module_utils/iosxr/facts/l2_interfaces/l2_interfaces.py @@ -0,0 +1,97 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright 2019 Red Hat Inc. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +""" +The iosxr l2 interfaces fact class +It is in this file the configuration is collected from the device +for a given resource, parsed, and the facts tree is populated +based on the configuration. +""" + +import re +from copy import deepcopy + +from ansible.module_utils.iosxr.facts.base import FactsBase +from ansible.module_utils.iosxr.utils.utils import get_interface_type, normalize_interface + + +class InterfacesFacts(FactsBase): + """ The iosxr l2 interfaces fact class + """ + + def populate_facts(self, module, connection, data=None): + """ Populate the facts for l2_interfaces + + :param module: the module instance + :param connection: the device connection + :param data: previously collected conf + :rtype: dictionary + :returns: facts + """ + if module: #just for linting purposes + pass + if connection: #just for linting purposes + pass + + if not data: + data = connection.get('show running-config interface') + + # operate on a collection of resource x + config = [data] # data.split('interface ') + objs = [] + for conf in config: + if conf: + obj = self.render_config(self.generated_spec, conf) + if obj: + objs.append(obj) + facts = {} + if objs: + facts['l2_interfaces'] = objs + self.ansible_facts['ansible_network_resources'].update(facts) + return self.ansible_facts + + def render_config(self, spec, conf): + """ + Render config as dictionary structure and delete keys from spec for null values + :param spec: The facts tree, generated from the argspec + :param conf: The configuration + :rtype: dictionary + :returns: The generated config + """ + config = deepcopy(spec) + match = re.search(r'^(\S+)', conf) + intf = match.group(1) + + if get_interface_type(intf) == 'unknown': + return {} + # populate the facts from the configuration + config['name'] = normalize_interface(intf) + + has_access = re.search(r"switchport access vlan (\d+)", conf) + if has_access: + config["access"] = {"vlan": int(has_access.group(1))} + + has_trunk = re.findall(r"switchport trunk (.+)", conf) + if has_trunk: + trunk = {} + for match in has_trunk: + has_encapsulation = re.match(r"encapsulation (\S+)", match) + if has_encapsulation: + trunk["encapsulation"] = has_encapsulation.group(1) + continue + has_native = re.match(r"native vlan (\d+)", match) + if has_native: + trunk["native_vlan"] = int(has_native.group(1)) + continue + has_allowed = re.match(r"allowed vlan (\S+)", match) + if has_allowed: + trunk["allowed_vlans"] = has_allowed.group(1) + continue + has_pruning = re.match(r"pruning vlan (\S+)", match) + if has_pruning: + trunk["pruning_vlans"] = has_pruning.group(1) + continue + config['trunk'] = trunk + + return self.generate_final_config(config) \ No newline at end of file From bc9f14ffdb5f52f74b518ef39409c50426a761f9 Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Sun, 26 May 2019 16:37:32 +0530 Subject: [PATCH 24/44] iosxr l2 interface Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/facts/resource/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 module_utils/iosxr/facts/resource/__init__.py diff --git a/module_utils/iosxr/facts/resource/__init__.py b/module_utils/iosxr/facts/resource/__init__.py new file mode 100644 index 0000000..e69de29 From 027aa4a41adaf5286655bfe1d785d7db5956271e Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Sun, 26 May 2019 16:37:33 +0530 Subject: [PATCH 25/44] iosxr l2 interface Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/facts/resource/resource.py | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 module_utils/iosxr/facts/resource/resource.py diff --git a/module_utils/iosxr/facts/resource/resource.py b/module_utils/iosxr/facts/resource/resource.py new file mode 100644 index 0000000..736bb02 --- /dev/null +++ b/module_utils/iosxr/facts/resource/resource.py @@ -0,0 +1,63 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# {{ rm['COPYRIGHT'] }} +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +""" +The iosxr_l2_interfaces fact class +It is in this file the configuration is collected from the device +for a given resource, parsed, and the facts tree is populated +based on the configuration. +""" +from copy import deepcopy +from ansible.module_utils.iosxr.facts.base import FactsBase + +class Facts(FactsBase): + """ The iosxr l2 fact class + """ + + def populate_facts(self, module, connection, data=None): + """ Populate the facts for l2_interfaces + + :param module: the module instance + :param connection: the device connection + :param data: previously collected conf + :rtype: dictionary + :returns: facts + """ + if module: #just for linting purposes + pass + if connection: #just for linting purposes + pass + + if not data: + data = "foo" # connection.get('show running-config | section ^interface') + + # operate on a collection of resource x + config = [data] # data.split('interface ') + objs = [] + for conf in config: + if conf: + obj = self.render_config(self.generated_spec, conf) + if obj: + objs.append(obj) + facts = {} + if objs: + facts['l2_interfaces'] = objs + self.ansible_facts['ansible_network_resources'].update(facts) + return self.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 + """ + if conf: + pass + config = deepcopy(spec) + # populate the facts from the configuration + config = {"some": "value"} + return self.generate_final_config(config) \ No newline at end of file From 3c449080e2aa38b2b48ecd2a65110d0247b3be41 Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Sun, 26 May 2019 16:40:22 +0530 Subject: [PATCH 26/44] iosxr l2 interface Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/utils/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 module_utils/iosxr/utils/__init__.py diff --git a/module_utils/iosxr/utils/__init__.py b/module_utils/iosxr/utils/__init__.py new file mode 100644 index 0000000..e69de29 From 1de53e70bc14c5fc97a372f540068339e3d4c694 Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Sun, 26 May 2019 16:40:22 +0530 Subject: [PATCH 27/44] iosxr l2 interface Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/utils/utils.py | 93 +++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 module_utils/iosxr/utils/utils.py diff --git a/module_utils/iosxr/utils/utils.py b/module_utils/iosxr/utils/utils.py new file mode 100644 index 0000000..aaceab2 --- /dev/null +++ b/module_utils/iosxr/utils/utils.py @@ -0,0 +1,93 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright 2019 Red Hat Inc. +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +# utils + + +def search_obj_in_list(name, lst): + for o in lst: + if o['name'] == name: + return o + return None + + +def normalize_interface(name): + """Return the normalized interface name + """ + if not name: + return + + def _get_number(name): + digits = '' + for char in name: + if char.isdigit() or char in '/.': + digits += char + return digits + + if name.lower().startswith('gi'): + if_type = 'GigabitEthernet' + elif name.lower().startswith('fa'): + if_type = 'FastEthernet' + elif name.lower().startswith('fo'): + if_type = 'FortyGigE' + elif name.lower().startswith('et'): + if_type = 'Ethernet' + elif name.lower().startswith('vl'): + if_type = 'Vlan' + elif name.lower().startswith('lo'): + if_type = 'loopback' + elif name.lower().startswith('po'): + if_type = 'port-channel' + elif name.lower().startswith('nv'): + if_type = 'nve' + elif name.lower().startswith('twe'): + if_type = 'TwentyFiveGigE' + elif name.lower().startswith('hu'): + if_type = 'HundredGigE' + else: + if_type = None + + number_list = name.split(' ') + if len(number_list) == 2: + number = number_list[-1].strip() + else: + number = _get_number(name) + + if if_type: + proper_interface = if_type + number + else: + proper_interface = name + + return proper_interface + + +def get_interface_type(interface): + """Gets the type of interface + """ + + if interface.upper().startswith('GI'): + return 'GigabitEthernet' + elif interface.upper().startswith('FA'): + return 'FastEthernet' + elif interface.upper().startswith('FO'): + return 'FortyGigE' + elif interface.upper().startswith('ET'): + return 'Ethernet' + elif interface.upper().startswith('VL'): + return 'Vlan' + elif interface.upper().startswith('LO'): + return 'loopback' + elif interface.upper().startswith('PO'): + return 'port-channel' + elif interface.upper().startswith('NV'): + return 'nve' + elif interface.upper().startswith('TWE'): + return 'TwentyFiveGigE' + elif interface.upper().startswith('HU'): + return 'HundredGigE' + elif interface.upper().startswith('PRE'): + return 'preconfigure' + else: + return 'unknown' From 136bc0bc3736987ba17684b1353ac28eae0b51d9 Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Mon, 27 May 2019 16:48:52 +0530 Subject: [PATCH 28/44] fix review comment Signed-off-by: Sumit Jaiswal --- library/iosxr_facts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/iosxr_facts.py b/library/iosxr_facts.py index 4387577..0382a57 100644 --- a/library/iosxr_facts.py +++ b/library/iosxr_facts.py @@ -85,7 +85,7 @@ from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.connection import Connection -from ansible.module_utils.ios.facts.facts import Facts +from ansible.module_utils.iosxr.facts.facts import Facts def main(): """ From b1b1c83792efc0595776ddbce9d9a5ea31f30b0b Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Mon, 27 May 2019 16:49:06 +0530 Subject: [PATCH 29/44] fix review comment Signed-off-by: Sumit Jaiswal --- library/iosxr_l2_interface.py | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/library/iosxr_l2_interface.py b/library/iosxr_l2_interface.py index 439cf3a..ab1efc6 100644 --- a/library/iosxr_l2_interface.py +++ b/library/iosxr_l2_interface.py @@ -46,8 +46,8 @@ --- module: iosxr_l2_interfaces version_added: 2.9 - short_description: Manage Layer-2 interface on Cisco IOS-XR devices. - description: This module provides declarative management of Layer-2 interface on Cisco IOS-XR devices. + short_description: Manage Layer-2 interface on Cisco IOS-XR devices + description: This module provides declarative management of a Layer-2 interface on Cisco IOS-XR devices. author: Sumit Jaiswal (@justjais) options: config: @@ -58,7 +58,7 @@ name: description: - Full name of the interface/sub-interface excluding any logical unit number, - i.e. GigabitEthernet0/0/0/1 or GigabitEthernet0/0/0/1.100. + e.g. GigabitEthernet0/0/0/1 or GigabitEthernet0/0/0/1.100. type: str required: True native_vlan: @@ -67,7 +67,7 @@ type: str l2transport: description: - - Switchport mode access command to configure the interface as a layer 2 access. + - Switchport mode access command to configure the interface as a layer 2 access type: bool l2protocol: description: @@ -80,28 +80,28 @@ type: str pvst: description: - - Configures VLAN spanning tree protocol tunneling and data unit parameters. + - Configures the per-VLAN Spanning Tree Protocol (PVST) tunneling and data unit parameters. choices: ['drop','forward', 'tunnel'] type: str stp: description: - - Spanning tree protocol tunneling and data unit parameters. + - Spanning Tree Protocol (STP) tunneling and data unit parameters. choices: ['drop','forward', 'tunnel'] type: str vtp: description: - - VLAN trunk protocol tunneling and data unit parameters. + - VLAN Trunk Protocol (VTP) tunneling and data unit parameters. choices: ['drop','forward', 'tunnel'] type: str q_vlan: description: - - 802.1Q VLAN configuration. Note that it can accept either 2 VLAN IDs when configuring Q-in-Q vlan, - or it shall accept 1 VLAN ID and 'any' as input list when configuring Q-in-any vlan as input. - type: str + - 802.1Q VLAN configuration. Note that it can accept either 2 VLAN IDs when configuring Q-in-Q VLAN, + or it will accept 1 VLAN ID and 'any' as input list when configuring Q-in-any vlan as input. Note, that + this option is valid only with respect to Sub-Interface and is not valid when configuring for Interface. + type: list propagate: description: - - Propagate Layer 2 transport events. Note that it will work only when l2tranport param is set - to True. + - Propagate Layer 2 transport events. Note that it will work only when the I(l2tranport) option is set to True type: bool state: choices: @@ -202,7 +202,7 @@ # ! - name: Replaces device configuration of listed interfaces with provided configuration - iosxr_interfaces: + iosxr_l2_interfaces: config: - name: GigabitEthernet0/0/0/4 native_vlan: 40 @@ -213,7 +213,7 @@ q_vlan: - 20 - any - state: overridden + state: replaced # After state: # ------------- @@ -264,7 +264,7 @@ # ! - name: Override device configuration of all interfaces with provided configuration - iosxr_interfaces: + iosxr_l2_interfaces: config: - name: GigabitEthernet0/0/0/4 native_vlan: 40 @@ -321,7 +321,7 @@ # ! # ! -- name: Delete attributes of given interfaces (Note: This won't delete the interface itself) +- name: Delete L2 attributes of given interfaces (Note: This won't delete the interface itself) iosxr_l2_interfaces: config: - name: GigabitEthernet0/0/0/3 From 1e19d44dd253100f16602eb3e68a42b367da5d4f Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Mon, 27 May 2019 16:49:17 +0530 Subject: [PATCH 30/44] fix review comment Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/argspec/l2_interfaces/l2_interfaces.py | 1 + 1 file changed, 1 insertion(+) diff --git a/module_utils/iosxr/argspec/l2_interfaces/l2_interfaces.py b/module_utils/iosxr/argspec/l2_interfaces/l2_interfaces.py index 138b55d..703a508 100644 --- a/module_utils/iosxr/argspec/l2_interfaces/l2_interfaces.py +++ b/module_utils/iosxr/argspec/l2_interfaces/l2_interfaces.py @@ -43,6 +43,7 @@ def __init__(self, **kwargs): 'l2transport': dict(element=dict, type=bool), 'l2protocol': dict(element=dict, type=list, options=l2_protocol_arg_spec), 'q_vlan':dict(element=dict, type=list), + 'propagate': dict(element=dict, type=bool) } argument_spec = { From b0c7924d9e60fc8a3a01e1ad1f2a0e35ade6877c Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Mon, 27 May 2019 16:49:28 +0530 Subject: [PATCH 31/44] fix review comment Signed-off-by: Sumit Jaiswal --- .../config/l2_interfaces/l2_interfaces.py | 180 ++++++++++++++++-- 1 file changed, 167 insertions(+), 13 deletions(-) diff --git a/module_utils/iosxr/config/l2_interfaces/l2_interfaces.py b/module_utils/iosxr/config/l2_interfaces/l2_interfaces.py index 5c15910..3e731f4 100644 --- a/module_utils/iosxr/config/l2_interfaces/l2_interfaces.py +++ b/module_utils/iosxr/config/l2_interfaces/l2_interfaces.py @@ -11,12 +11,12 @@ """ from ansible.module_utils.network.common.utils import to_list +from ansible.module_utils.six import iteritems from ansible.module_utils.iosxr.argspec.l2_interfaces.l2_interfaces import L2_InterfacesArgs from ansible.module_utils.iosxr.config.base import ConfigBase from ansible.module_utils.iosxr.facts.facts import Facts -from ansible.module_utils.iosxr.utils.utils import get_interface_type, normalize_interface, search_obj_in_list -import q + class L2_Interfaces(ConfigBase, L2_InterfacesArgs): """ @@ -39,13 +39,9 @@ def get_l2_interfaces_facts(self): :returns: The current configuration as a dictionary """ result = Facts().get_facts(self._module, self._connection, self.gather_subset, self.gather_network_resources) - try: - facts = result[0] - q(facts) - except (TypeError, KeyError): - facts = result - l2_interfaces_facts = facts['ansible_network_resources'].get('l2_interfaces') - q(l2_interfaces_facts) + facts = result + l2_interfaces_facts = facts['ansible_network_resources'].get('l2_interfaces') + if not l2_interfaces_facts: return [] return l2_interfaces_facts @@ -99,19 +95,22 @@ def set_state(self, want, have): :returns: the commands necessary to migrate the current configuration to the desired configuration """ + commands = [] + state = self._module.params['state'] if state == 'overridden': - kwargs = {} + kwargs = {'want': want, 'have': have, 'module': self._module} commands = self._state_overridden(**kwargs) elif state == 'deleted': - kwargs = {} + kwargs = {'want': want, 'have': have, 'module': self._module} commands = self._state_deleted(**kwargs) elif state == 'merged': - kwargs = {} + kwargs = {'want': want, 'have': have, 'module': self._module} commands = self._state_merged(**kwargs) elif state == 'replaced': - kwargs = {} + kwargs = {'want': want, 'have': have, 'module': self._module} commands = self._state_replaced(**kwargs) + return commands @staticmethod @@ -123,6 +122,23 @@ def _state_replaced(**kwargs): to the desired configuration """ commands = [] + want = kwargs['want'] + have = kwargs['have'] + module = kwargs['module'] + + for interface in want: + for each in have: + if each['name'] == interface['name']: + break + elif interface['name'] in each['name']: + break + else: + continue + kwargs = {'want': interface, 'have': each, } + commands.extend(L2_Interfaces.clear_interface(**kwargs)) + kwargs = {'want': interface, 'have': each, 'commands': commands, 'module': module} + commands.extend(L2_Interfaces.set_interface(**kwargs)) + return commands @staticmethod @@ -134,6 +150,28 @@ def _state_overridden(**kwargs): to the desired configuration """ commands = [] + want = kwargs['want'] + have = kwargs['have'] + module = kwargs['module'] + + for each in have: + for interface in want: + if each['name'] == interface['name']: + break + elif interface['name'] in each['name']: + break + else: + # We didn't find a matching desired state, which means we can + # pretend we recieved an empty desired state. + interface = dict(name=each['name']) + kwargs = {'want': interface, 'have': each} + commands.extend(L2_Interfaces.clear_interface(**kwargs)) + continue + kwargs = {'want': interface, 'have': each} + commands.extend(L2_Interfaces.clear_interface(**kwargs)) + kwargs = {'want': interface, 'have': each, 'commands': commands, 'module': module} + commands.extend(L2_Interfaces.set_interface(**kwargs)) + return commands @staticmethod @@ -145,6 +183,21 @@ def _state_merged(**kwargs): the current configuration """ commands = [] + want = kwargs['want'] + have = kwargs['have'] + module = kwargs['module'] + + for interface in want: + for each in have: + if each['name'] == interface['name']: + break + elif interface['name'] in each['name']: + break + else: + continue + kwargs = {'want': interface, 'have': each, 'module': module} + commands.extend(L2_Interfaces.set_interface(**kwargs)) + return commands @staticmethod @@ -156,4 +209,105 @@ def _state_deleted(**kwargs): of the provided objects """ commands = [] + want = kwargs['want'] + have = kwargs['have'] + + for interface in want: + for each in have: + if each['name'] == interface['name']: + break + elif interface['name'] in each['name']: + break + else: + continue + interface = dict(name=interface['name']) + kwargs = {'want': interface, 'have': each} + commands.extend(L2_Interfaces.clear_interface(**kwargs)) + + return commands + + @staticmethod + def _remove_command_from_interface(interface, cmd, commands): + if interface not in commands: + commands.insert(0, interface) + commands.append('no %s' % cmd) + return commands + + @staticmethod + def _add_command_to_interface(interface, cmd, commands): + if interface not in commands: + commands.insert(0, interface) + commands.append(cmd) + + @staticmethod + def set_interface(**kwargs): + # Set the interface config based on the want and have config + commands = [] + want = kwargs['want'] + have = kwargs['have'] + module = kwargs['module'] + clear_cmds = [] + if kwargs.get('commands'): + clear_cmds = kwargs['commands'] + + interface = 'interface ' + want['name'] + wants_native = want["native_vlan"] + if wants_native and wants_native != str(have.get("native_vlan", {}).get("vlan")) or\ + 'no dot1q native vlan' in clear_cmds: + cmd = 'dot1q native vlan {}'.format(wants_native) + L2_Interfaces._add_command_to_interface(interface, cmd, commands) + + if want.get('l2transport'): + if want.get('l2protocol'): + for each in want.get('l2protocol'): + for k, v in iteritems(each): + l2ptotocol_type = 'l2protocol_' + k + if have.get(l2ptotocol_type) != v: + cmd = 'l2transport l2protocol ' + k + ' ' + v + L2_Interfaces._add_command_to_interface(interface, cmd, commands) + if want.get('propagate') and not have.get('propagate'): + cmd = 'l2transport propagate remote-status' + L2_Interfaces._add_command_to_interface(interface, cmd, commands) + elif want.get('l2protocol') or want.get('propagate'): + module.fail_json(msg='L2transports L2protocol or Propagate can only be configured when' + 'L2transprt set to True!') + + if want.get('q_vlan'): + q_vlans = (" ".join(map(str, want.get('q_vlan')))) + if q_vlans != have.get('q_vlan'): + if 'any' in q_vlans and 'l2transport' in interface: + cmd = 'dot1q vlan {}'.format(q_vlans) + L2_Interfaces._add_command_to_interface(interface, cmd, commands) + else: + cmd = 'dot1q vlan {}'.format(q_vlans) + L2_Interfaces._add_command_to_interface(interface, cmd, commands) + + return commands + + @staticmethod + def clear_interface(**kwargs): + # Delete the interface config based on the want and have config + commands = [] + want = kwargs['want'] + have = kwargs['have'] + interface = 'interface ' + want['name'] + + if 'q_vlan' in have and 'l2transport' in have['name'] and want['name'] in have['name']: + L2_Interfaces._remove_command_from_interface(interface, 'dot1q vlan', commands) + elif 'q_vlan' in have and 'l2transport' not in have['name'] and want['name'] in have['name']: + L2_Interfaces._remove_command_from_interface(interface, 'encapsulation dot1q', commands) + + if 'native_vlan' in have and want.get('native_vlan') != have.get('native_vlan'): + L2_Interfaces._remove_command_from_interface(interface, 'dot1q native vlan', commands) + if want.get('l2transport'): + if want.get('l2protocol'): + for each in want.get('l2protocol'): + for k, v in iteritems(each): + l2ptotocol_type = 'l2protocol_' + k + if have.get(l2ptotocol_type) != v: + L2_Interfaces._remove_command_from_interface(interface, 'l2transport', commands) + if have.get('l2transport') and not want.get('l2transport'): + if 'no l2transport' not in commands: + L2_Interfaces._remove_command_from_interface(interface, 'l2transport', commands) + return commands \ No newline at end of file From fb9ea64541f6ca94be1e974a0f64514aa8dee02f Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Mon, 27 May 2019 16:49:37 +0530 Subject: [PATCH 32/44] fix review comment Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/facts/facts.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/module_utils/iosxr/facts/facts.py b/module_utils/iosxr/facts/facts.py index 8d980f6..5057ec1 100644 --- a/module_utils/iosxr/facts/facts.py +++ b/module_utils/iosxr/facts/facts.py @@ -14,8 +14,8 @@ from ansible.module_utils.iosxr.argspec.facts.facts import FactsArgs from ansible.module_utils.iosxr.facts.base import FactsBase from ansible.module_utils.iosxr.argspec.l2_interfaces.l2_interfaces import L2_InterfacesArgs -from ansible.module_utils.iosxr.facts.l2_interfaces.l2_interfaces import InterfacesFacts -import q +from ansible.module_utils.iosxr.facts.l2_interfaces.l2_interfaces import L2_interfacesFacts + FACT_SUBSETS = {} @@ -85,11 +85,8 @@ def get_facts(self, module, connection, gather_subset=['!config'], gather_networ resources_runable_subsets = self.generate_runable_subsets(module, gather_network_resources, valid_network_resources_subsets) if resources_runable_subsets: self.ansible_facts['gather_network_resources'] = list(resources_runable_subsets) - q(resources_runable_subsets) for attr in resources_runable_subsets: - q(attr, module, connection) getattr(self, '_get_%s' % attr, {})(module, connection) - if self.VALID_GATHER_SUBSETS: runable_subsets = self.generate_runable_subsets(module, gather_subset, self.VALID_GATHER_SUBSETS) @@ -117,5 +114,5 @@ def get_facts(self, module, connection, gather_subset=['!config'], gather_networ @staticmethod - def _get_net_configuration_interfaces(module, connection): - return InterfacesFacts(L2_InterfacesArgs.argument_spec, 'config', 'options').populate_facts(module, connection) \ No newline at end of file + def _get_l2_interfaces(module, connection): + return L2_interfacesFacts(L2_InterfacesArgs.argument_spec, 'config', 'options').populate_facts(module, connection) \ No newline at end of file From 709b071965026361cafc345e698e262beeec609f Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Mon, 27 May 2019 16:49:46 +0530 Subject: [PATCH 33/44] fix review comment Signed-off-by: Sumit Jaiswal --- .../facts/l2_interfaces/l2_interfaces.py | 68 +++++++++---------- 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/module_utils/iosxr/facts/l2_interfaces/l2_interfaces.py b/module_utils/iosxr/facts/l2_interfaces/l2_interfaces.py index 97b1ed7..e176236 100644 --- a/module_utils/iosxr/facts/l2_interfaces/l2_interfaces.py +++ b/module_utils/iosxr/facts/l2_interfaces/l2_interfaces.py @@ -16,13 +16,12 @@ from ansible.module_utils.iosxr.utils.utils import get_interface_type, normalize_interface -class InterfacesFacts(FactsBase): +class L2_interfacesFacts(FactsBase): """ The iosxr l2 interfaces fact class """ def populate_facts(self, module, connection, data=None): """ Populate the facts for l2_interfaces - :param module: the module instance :param connection: the device connection :param data: previously collected conf @@ -33,13 +32,12 @@ def populate_facts(self, module, connection, data=None): pass if connection: #just for linting purposes pass - + objs = [] if not data: data = connection.get('show running-config interface') # operate on a collection of resource x - config = [data] # data.split('interface ') - objs = [] + config = data.split('interface ') for conf in config: if conf: obj = self.render_config(self.generated_spec, conf) @@ -61,37 +59,37 @@ def render_config(self, spec, conf): """ config = deepcopy(spec) match = re.search(r'^(\S+)', conf) - intf = match.group(1) - - if get_interface_type(intf) == 'unknown': - return {} - # populate the facts from the configuration - config['name'] = normalize_interface(intf) - has_access = re.search(r"switchport access vlan (\d+)", conf) - if has_access: - config["access"] = {"vlan": int(has_access.group(1))} + if len(match.group().split('.')) > 1: + sub_match = re.search(r'^(\S+ \S+)', conf) + if sub_match: + intf = sub_match.group() + config['name'] = intf + else: + intf = match.group(1) + config['name'] = intf + else: + intf = match.group(1) + if get_interface_type(intf) == 'unknown': + return {} + # populate the facts from the configuration + config['name'] = normalize_interface(intf) + native_vlan = re.search(r"dot1q native vlan (\d+)", conf) + if native_vlan: + config["native_vlan"] = {"vlan": int(native_vlan.group(1))} + if 'l2transport' in config['name']: + config['q_vlan'] = self.parse_conf_arg(conf, 'dot1q vlan') + else: + config['q_vlan'] = self.parse_conf_arg(conf, 'encapsulation dot1q') - has_trunk = re.findall(r"switchport trunk (.+)", conf) - if has_trunk: - trunk = {} - for match in has_trunk: - has_encapsulation = re.match(r"encapsulation (\S+)", match) - if has_encapsulation: - trunk["encapsulation"] = has_encapsulation.group(1) - continue - has_native = re.match(r"native vlan (\d+)", match) - if has_native: - trunk["native_vlan"] = int(has_native.group(1)) - continue - has_allowed = re.match(r"allowed vlan (\S+)", match) - if has_allowed: - trunk["allowed_vlans"] = has_allowed.group(1) - continue - has_pruning = re.match(r"pruning vlan (\S+)", match) - if has_pruning: - trunk["pruning_vlans"] = has_pruning.group(1) - continue - config['trunk'] = trunk + if self.parse_conf_arg(conf, 'propagate'): + config['propagate'] = True + config['l2protocol_cdp'] = self.parse_conf_arg(conf, 'l2protocol cdp') + config['l2protocol_pvst'] = self.parse_conf_arg(conf, 'l2protocol pvst') + config['l2protocol_stp'] = self.parse_conf_arg(conf, 'l2protocol stp') + config['l2protocol_vtp'] = self.parse_conf_arg(conf, 'l2protocol vtp') + if config.get('propagate') or config.get('l2protocol_cdp') or config.get('l2protocol_pvst') or\ + config.get('l2protocol_stp') or config.get('l2protocol_vtp'): + config['l2transport'] = True return self.generate_final_config(config) \ No newline at end of file From f5dd9d083e63ded052c61e36bd7f427d21c14b74 Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Mon, 27 May 2019 19:46:32 +0530 Subject: [PATCH 34/44] fix idempotency Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/config/l2_interfaces/l2_interfaces.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module_utils/iosxr/config/l2_interfaces/l2_interfaces.py b/module_utils/iosxr/config/l2_interfaces/l2_interfaces.py index 3e731f4..4dc9113 100644 --- a/module_utils/iosxr/config/l2_interfaces/l2_interfaces.py +++ b/module_utils/iosxr/config/l2_interfaces/l2_interfaces.py @@ -297,7 +297,7 @@ def clear_interface(**kwargs): elif 'q_vlan' in have and 'l2transport' not in have['name'] and want['name'] in have['name']: L2_Interfaces._remove_command_from_interface(interface, 'encapsulation dot1q', commands) - if 'native_vlan' in have and want.get('native_vlan') != have.get('native_vlan'): + if 'native_vlan' in have and want.get('native_vlan') != str(have.get('native_vlan').get('vlan')): L2_Interfaces._remove_command_from_interface(interface, 'dot1q native vlan', commands) if want.get('l2transport'): if want.get('l2protocol'): From 92c4f37c05cfbf6e429e5e6366c36f3ad4bbda27 Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Wed, 29 May 2019 18:27:02 +0530 Subject: [PATCH 35/44] bug n doc fix Signed-off-by: Sumit Jaiswal --- library/iosxr_facts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/iosxr_facts.py b/library/iosxr_facts.py index 0382a57..207665b 100644 --- a/library/iosxr_facts.py +++ b/library/iosxr_facts.py @@ -1,6 +1,6 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -# {{ rm['COPYRIGHT'] }} +# Copyright 2019 Red Hat Inc. # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) """ The module file for iosxr_facts From 2135b4d204934563491326ac48f68d5ccf6d1e91 Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Wed, 29 May 2019 18:27:13 +0530 Subject: [PATCH 36/44] bug n doc fix Signed-off-by: Sumit Jaiswal --- library/iosxr_l2_interface.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/library/iosxr_l2_interface.py b/library/iosxr_l2_interface.py index ab1efc6..45a0e6c 100644 --- a/library/iosxr_l2_interface.py +++ b/library/iosxr_l2_interface.py @@ -1,6 +1,6 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -# {{ rm['COPYRIGHT'] }} +# Copyright 2019 Red Hat Inc. # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) ############################################## @@ -30,8 +30,6 @@ from __future__ import absolute_import, division, print_function __metaclass__ = type -#{{ rm|to_doc(model) }} - GENERATOR_VERSION = '1.0' ANSIBLE_METADATA = {'metadata_version': '1.1', From 57e7117abbaf73d671b68429a07ee38596b17963 Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Wed, 29 May 2019 18:27:23 +0530 Subject: [PATCH 37/44] bug n doc fix Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/argspec/facts/facts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module_utils/iosxr/argspec/facts/facts.py b/module_utils/iosxr/argspec/facts/facts.py index 88d8755..72bd9b2 100644 --- a/module_utils/iosxr/argspec/facts/facts.py +++ b/module_utils/iosxr/argspec/facts/facts.py @@ -1,6 +1,6 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -# {{ rm['COPYRIGHT'] }} +# Copyright 2019 Red Hat Inc. # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) """ The arg spec for the iosxr facts module. From a6116332ef70eedb608b5650c0fba8630ff383a3 Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Wed, 29 May 2019 18:27:33 +0530 Subject: [PATCH 38/44] bug n doc fix Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/argspec/resource/resource.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module_utils/iosxr/argspec/resource/resource.py b/module_utils/iosxr/argspec/resource/resource.py index 3c343e7..c97a539 100644 --- a/module_utils/iosxr/argspec/resource/resource.py +++ b/module_utils/iosxr/argspec/resource/resource.py @@ -1,6 +1,6 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -# {{ rm['COPYRIGHT'] }} +# Red Hat # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) ############################################# From 752aaa7adbb8efaf9a3a042e867e9129ae501f5a Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Wed, 29 May 2019 18:27:45 +0530 Subject: [PATCH 39/44] bug n doc fix Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/config/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module_utils/iosxr/config/base.py b/module_utils/iosxr/config/base.py index 99e9d1e..7ef97ea 100644 --- a/module_utils/iosxr/config/base.py +++ b/module_utils/iosxr/config/base.py @@ -1,6 +1,6 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -# {{ rm['COPYRIGHT'] }} +# Copyright 2019 Red Hat Inc. # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) """ The base class for all iosxr resource modules From c4af8f8a2edc4fa78421b6d99cc58bcb0ac543a4 Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Wed, 29 May 2019 18:27:57 +0530 Subject: [PATCH 40/44] bug n doc fix Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/config/l2_interfaces/l2_interfaces.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/module_utils/iosxr/config/l2_interfaces/l2_interfaces.py b/module_utils/iosxr/config/l2_interfaces/l2_interfaces.py index 4dc9113..f481bb6 100644 --- a/module_utils/iosxr/config/l2_interfaces/l2_interfaces.py +++ b/module_utils/iosxr/config/l2_interfaces/l2_interfaces.py @@ -292,7 +292,8 @@ def clear_interface(**kwargs): have = kwargs['have'] interface = 'interface ' + want['name'] - if 'q_vlan' in have and 'l2transport' in have['name'] and want['name'] in have['name']: + if 'q_vlan' in have and 'l2transport' in have['name'] and want['name'] in have['name']\ + and (" ".join(map(str, want.get('q_vlan')))) != have.get('q_vlan'): L2_Interfaces._remove_command_from_interface(interface, 'dot1q vlan', commands) elif 'q_vlan' in have and 'l2transport' not in have['name'] and want['name'] in have['name']: L2_Interfaces._remove_command_from_interface(interface, 'encapsulation dot1q', commands) From a6054f701021ee4d4e71659b1eec943d30ca048b Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Wed, 29 May 2019 18:28:05 +0530 Subject: [PATCH 41/44] bug n doc fix Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/facts/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module_utils/iosxr/facts/base.py b/module_utils/iosxr/facts/base.py index 5c36d83..8c1a03d 100644 --- a/module_utils/iosxr/facts/base.py +++ b/module_utils/iosxr/facts/base.py @@ -1,6 +1,6 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -# {{ rm['COPYRIGHT'] }} +# Copyright 2019 Red Hat Inc. # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) """ The iosxr facts base class From 9079a8bcd939fa31c36d7907d55808af0db332a2 Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Wed, 29 May 2019 18:28:13 +0530 Subject: [PATCH 42/44] bug n doc fix Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/facts/facts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module_utils/iosxr/facts/facts.py b/module_utils/iosxr/facts/facts.py index 5057ec1..e6253aa 100644 --- a/module_utils/iosxr/facts/facts.py +++ b/module_utils/iosxr/facts/facts.py @@ -1,6 +1,6 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -# {{ rm['COPYRIGHT'] }} +# Copyright 2019 Red Hat Inc. # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) """ The facts class for iosxr From 34e9b60139891b82663033b0e9c5c736c40c567c Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Wed, 29 May 2019 18:28:24 +0530 Subject: [PATCH 43/44] bug n doc fix Signed-off-by: Sumit Jaiswal --- module_utils/iosxr/facts/resource/resource.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module_utils/iosxr/facts/resource/resource.py b/module_utils/iosxr/facts/resource/resource.py index 736bb02..1d5daca 100644 --- a/module_utils/iosxr/facts/resource/resource.py +++ b/module_utils/iosxr/facts/resource/resource.py @@ -1,6 +1,6 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -# {{ rm['COPYRIGHT'] }} +# Copyright 2019 Red Hat Inc. # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) """ The iosxr_l2_interfaces fact class From 6d22d397eb945fc78183a502792bab7a9f3a1e40 Mon Sep 17 00:00:00 2001 From: Sumit Jaiswal Date: Thu, 8 Aug 2019 14:24:59 +0530 Subject: [PATCH 44/44] fix issues --- .idea/libraries/R_User_Library.xml | 6 + .idea/misc.xml | 4 + .idea/modules.xml | 8 + .idea/network.iml | 13 + .idea/vcs.xml | 6 + .idea/workspace.xml | 508 ++++++++++++++++++ ...l2_interface.py => iosxr_l2_interfaces.py} | 127 +++-- module_utils/iosxr/argspec/facts/facts.py | 24 - .../argspec/l2_interfaces/l2_interfaces.py | 52 -- .../iosxr/argspec/resource/resource.py | 27 - .../config/l2_interfaces/l2_interfaces.py | 314 ----------- module_utils/iosxr/facts/facts.py | 118 ---- .../facts/l2_interfaces/l2_interfaces.py | 95 ---- module_utils/iosxr/utils/utils.py | 93 ---- module_utils/{iosxr => network}/__init__.py | 0 .../facts => network/iosxr}/__init__.py | 0 .../{ => network}/iosxr/argspec/__init__.py | 0 .../iosxr/argspec/facts}/__init__.py | 0 .../network/iosxr/argspec/facts/facts.py | 30 ++ .../iosxr/argspec/l2_interfaces}/__init__.py | 0 .../argspec/l2_interfaces/l2_interfaces.py | 57 ++ .../{ => network}/iosxr/config/__init__.py | 0 .../{ => network}/iosxr/config/base.py | 0 .../iosxr/config/l2_interfaces/__init__.py | 0 .../config/l2_interfaces/l2_interfaces.py | 308 +++++++++++ .../iosxr/config/resource/__init__.py | 0 .../iosxr/config/resource/resource.py | 0 .../{ => network}/iosxr/facts/__init__.py | 0 .../{ => network}/iosxr/facts/base.py | 0 module_utils/network/iosxr/facts/facts.py | 62 +++ .../iosxr/facts/l2_interfaces/__init__.py | 0 .../facts/l2_interfaces/l2_interfaces.py | 129 +++++ .../iosxr/facts/resource/__init__.py | 0 .../iosxr/facts/resource/resource.py | 0 .../{ => network}/iosxr/utils/__init__.py | 0 module_utils/network/iosxr/utils/utils.py | 165 ++++++ 36 files changed, 1379 insertions(+), 767 deletions(-) create mode 100644 .idea/libraries/R_User_Library.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/network.iml create mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml rename library/{iosxr_l2_interface.py => iosxr_l2_interfaces.py} (75%) delete mode 100644 module_utils/iosxr/argspec/facts/facts.py delete mode 100644 module_utils/iosxr/argspec/l2_interfaces/l2_interfaces.py delete mode 100644 module_utils/iosxr/argspec/resource/resource.py delete mode 100644 module_utils/iosxr/config/l2_interfaces/l2_interfaces.py delete mode 100644 module_utils/iosxr/facts/facts.py delete mode 100644 module_utils/iosxr/facts/l2_interfaces/l2_interfaces.py delete mode 100644 module_utils/iosxr/utils/utils.py rename module_utils/{iosxr => network}/__init__.py (100%) rename module_utils/{iosxr/argspec/facts => network/iosxr}/__init__.py (100%) rename module_utils/{ => network}/iosxr/argspec/__init__.py (100%) rename module_utils/{iosxr/argspec/l2_interfaces => network/iosxr/argspec/facts}/__init__.py (100%) create mode 100644 module_utils/network/iosxr/argspec/facts/facts.py rename module_utils/{iosxr/argspec/resource => network/iosxr/argspec/l2_interfaces}/__init__.py (100%) create mode 100644 module_utils/network/iosxr/argspec/l2_interfaces/l2_interfaces.py rename module_utils/{ => network}/iosxr/config/__init__.py (100%) rename module_utils/{ => network}/iosxr/config/base.py (100%) rename module_utils/{ => network}/iosxr/config/l2_interfaces/__init__.py (100%) create mode 100644 module_utils/network/iosxr/config/l2_interfaces/l2_interfaces.py rename module_utils/{ => network}/iosxr/config/resource/__init__.py (100%) rename module_utils/{ => network}/iosxr/config/resource/resource.py (100%) rename module_utils/{ => network}/iosxr/facts/__init__.py (100%) rename module_utils/{ => network}/iosxr/facts/base.py (100%) create mode 100644 module_utils/network/iosxr/facts/facts.py rename module_utils/{ => network}/iosxr/facts/l2_interfaces/__init__.py (100%) create mode 100644 module_utils/network/iosxr/facts/l2_interfaces/l2_interfaces.py rename module_utils/{ => network}/iosxr/facts/resource/__init__.py (100%) rename module_utils/{ => network}/iosxr/facts/resource/resource.py (100%) rename module_utils/{ => network}/iosxr/utils/__init__.py (100%) create mode 100644 module_utils/network/iosxr/utils/utils.py diff --git a/.idea/libraries/R_User_Library.xml b/.idea/libraries/R_User_Library.xml new file mode 100644 index 0000000..71f5ff7 --- /dev/null +++ b/.idea/libraries/R_User_Library.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..7ba73c2 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..a82482f --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/network.iml b/.idea/network.iml new file mode 100644 index 0000000..bf708e3 --- /dev/null +++ b/.idea/network.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..cb329fe --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,508 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + id + after + from __future__ + https://www.visa.go.kr/openPage.do?MENU_ID=10101&LANG_TYPE=EN + exit_json + int( + flowcontrol + interfaces + vlan + !/usr/bin/python + get_interfaces_facts + _clear_in + filter_dict_having_none_value + Interfaces. + re. + get_interface_type + normalize_interface + parse_conf_arg + clear_interface + l2protocol + l2ptotocol_type + l2protocol_ + propagate + re.search + dot1q native vla + l2_protocol_diff + int + ios + import q + q( + + + state + name + _set_config + _clear_config + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +