mirror of
https://github.com/ansible-collections/community.general.git
synced 2026-05-08 14:22:46 +00:00
Moving modules from lenovo to cnos (#31401)
* Moving modules from lenovo to cnos * Merge conflicts * Update cnos_conditional_template.py Removed 180:5: E265 block comment should start with '# ' 188:34: E226 missing whitespace around arithmetic operator * Update cnos_template.py 155:5: E265 block comment should start with '# ' 162:34: E226 missing whitespace around arithmetic operator * Update cnos_vlan.py 210:1: E302 expected 2 blank lines, found 1 * Update cnos_backup.py Adding from __future__ import (absolute_import, division, print_function) __metaclass__ = type * Update cnos_bgp.py Added from __future__ import (absolute_import, division, print_function) __metaclass__ = type * Update cnos_backup.py Added a line extra * Update cnos_command.py Adding from __future__ import (absolute_import, division, print_function) __metaclass__ = type * Update cnos_conditional_command.py Adding from __future__ import (absolute_import, division, print_function) __metaclass__ = type * Update cnos_conditional_template.py Adding from __future__ import (absolute_import, division, print_function) __metaclass__ = type * Update cnos_factory.py Adding from __future__ import (absolute_import, division, print_function) __metaclass__ = type * Update cnos_facts.py Adding from __future__ import (absolute_import, division, print_function) __metaclass__ = type * Update cnos_image.py Adding from __future__ import (absolute_import, division, print_function) __metaclass__ = type * Update cnos_interface.py Adding from __future__ import (absolute_import, division, print_function) __metaclass__ = type * Update cnos_portchannel.py Adding from __future__ import (absolute_import, division, print_function) __metaclass__ = type * Update cnos_reload.py Adding from __future__ import (absolute_import, division, print_function) __metaclass__ = type * Update cnos_rollback.py Adding from __future__ import (absolute_import, division, print_function) __metaclass__ = type * Update cnos_save.py Add from __future__ import (absolute_import, division, print_function) __metaclass__ = type * Update cnos_showrun.py Add from __future__ import (absolute_import, division, print_function) __metaclass__ = type * Update cnos_template.py Adding from __future__ import (absolute_import, division, print_function) __metaclass__ = type * Update cnos_vlag.py Adding from __future__ import (absolute_import, division, print_function) __metaclass__ = type * Update cnos_vlan.py Adding from __future__ import (absolute_import, division, print_function) __metaclass__ = type * Update cnos_backup.py Moving it to top of file * Update cnos_backup.py * Moving future and metaclass to top * Moving future and metaclass to top * Moving future and metaclass to top * Moving future and metaclass to top * Moving future and metaclass to top * Moving future and metaclass to top * Moving future and metaclass to top * Moving future and metaclass to top * Moving future and metaclass to top * Moving future and metaclass to top * Moving future and metaclass to top * Moving future and metaclass to top * Moving future and metaclass to top * Moving future and metaclass to top * Moving future and metaclass to top * Moving future and metaclass to top * Putting condition to bye pass paramiko * Condition to byepass paramiko import error * Condition to byepass paramiko import error * Condition to byepass paramiko import error * Condition to byepass paramiko import error * Condition to byepass paramiko import error * Condition to byepass paramiko import error * Condition to byepass paramiko import error * Condition to byepass paramiko import error * Condition to byepass paramiko import error * Condition to byepass paramiko import error * Condition to byepass paramiko import error * Condition to byepass paramiko import error * Condition to byepass paramiko import error * Condition to byepass paramiko import error * Condition to byepass paramiko import error * Condition to byepass paramiko import error * Removing unused import and white spaces * Dealing with white space and import issues * Dealing with white space and import issues * Dealing with white space and import issues * Dealing with white space and import issues * Dealing with white space and import issues * Dealing with white space and import issues * Dealing with white space and import issues * Dealing with white space and import issues * Dealing with white space and import issues * Dealing with white space and import issues * Dealing with white space and import issues * Dealing with white space and import issues * Dealing with white space and import issues * Dealing with white space and import issues * Dealing with white space and import issues * Dealing with white space and import issues * Update cnos_template.py
This commit is contained in:
committed by
John R Barker
parent
0b320ba15c
commit
8e081b7e30
0
lib/ansible/modules/network/cnos/__init__.py
Normal file
0
lib/ansible/modules/network/cnos/__init__.py
Normal file
298
lib/ansible/modules/network/cnos/cnos_backup.py
Normal file
298
lib/ansible/modules/network/cnos/cnos_backup.py
Normal file
@@ -0,0 +1,298 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
#
|
||||
# Copyright (C) 2017 Lenovo, 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/>.
|
||||
#
|
||||
# Module to Backup Config to Lenovo Switches
|
||||
# Lenovo Networking
|
||||
#
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: cnos_backup
|
||||
author: "Dave Kasberg (@dkasberg)"
|
||||
short_description: Backup the current running or startup configuration to a remote server on devices running Lenovo CNOS
|
||||
description:
|
||||
- This module allows you to work with switch configurations. It provides a
|
||||
way to back up the running or startup configurations of a switch to a
|
||||
remote server. This is achieved by periodically saving a copy of the
|
||||
startup or running configuration of the network device to a remote server
|
||||
using FTP, SFTP, TFTP, or SCP. The first step is to create a directory from
|
||||
where the remote server can be reached. The next step is to provide the
|
||||
full file path of the location where the configuration will be backed up.
|
||||
Authentication details required by the remote server must be provided as
|
||||
well. This module uses SSH to manage network device configuration.
|
||||
The results of the operation will be placed in a directory named 'results'
|
||||
that must be created by the user in their local directory to where the playbook is run.
|
||||
For more information about this module from Lenovo and customizing it usage for your
|
||||
use cases, please visit U(http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_backup.html)
|
||||
version_added: "2.3"
|
||||
extends_documentation_fragment: cnos
|
||||
options:
|
||||
configType:
|
||||
description:
|
||||
- This specifies what type of configuration will be backed up. The
|
||||
choices are the running or startup configurations. There is no
|
||||
default value, so it will result in an error if the input is
|
||||
incorrect.
|
||||
required: Yes
|
||||
default: Null
|
||||
choices: [running-config, startup-config]
|
||||
protocol:
|
||||
description:
|
||||
- This refers to the protocol used by the network device to
|
||||
interact with the remote server to where to upload the backup
|
||||
configuration. The choices are FTP, SFTP, TFTP, or SCP. Any other
|
||||
protocols will result in error. If this parameter is not specified,
|
||||
there is no default value to be used.
|
||||
required: Yes
|
||||
default: Null
|
||||
choices: [SFTP, SCP, FTP, TFTP]
|
||||
rcserverip:
|
||||
description:
|
||||
-This specifies the IP Address of the remote server to where the
|
||||
configuration will be backed up.
|
||||
required: Yes
|
||||
default: Null
|
||||
rcpath:
|
||||
description:
|
||||
- This specifies the full file path where the configuration file
|
||||
will be copied on the remote server. In case the relative path is
|
||||
used as the variable value, the root folder for the user of the
|
||||
server needs to be specified.
|
||||
required: Yes
|
||||
default: Null
|
||||
serverusername:
|
||||
description:
|
||||
- Specify the username for the server relating to the protocol
|
||||
used.
|
||||
required: Yes
|
||||
default: Null
|
||||
serverpassword:
|
||||
description:
|
||||
- Specify the password for the server relating to the protocol
|
||||
used.
|
||||
required: Yes
|
||||
default: Null
|
||||
'''
|
||||
EXAMPLES = '''
|
||||
Tasks : The following are examples of using the module cnos_backup. These are written in the main.yml file of the tasks directory.
|
||||
---
|
||||
- name: Test Running Config Backup
|
||||
cnos_backup:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_backup_{{ inventory_hostname }}_output.txt"
|
||||
configType: running-config
|
||||
protocol: "sftp"
|
||||
serverip: "10.241.106.118"
|
||||
rcpath: "/root/cnos/G8272-running-config.txt"
|
||||
serverusername: "root"
|
||||
serverpassword: "root123"
|
||||
|
||||
- name: Test Startup Config Backup
|
||||
cnos_backup:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_backup_{{ inventory_hostname }}_output.txt"
|
||||
configType: startup-config
|
||||
protocol: "sftp"
|
||||
serverip: "10.241.106.118"
|
||||
rcpath: "/root/cnos/G8272-startup-config.txt"
|
||||
serverusername: "root"
|
||||
serverpassword: "root123"
|
||||
|
||||
- name: Test Running Config Backup -TFTP
|
||||
cnos_backup:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_backup_{{ inventory_hostname }}_output.txt"
|
||||
configType: running-config
|
||||
protocol: "tftp"
|
||||
serverip: "10.241.106.118"
|
||||
rcpath: "/anil/G8272-running-config.txt"
|
||||
serverusername: "root"
|
||||
serverpassword: "root123"
|
||||
|
||||
- name: Test Startup Config Backup - TFTP
|
||||
cnos_backup:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_backup_{{ inventory_hostname }}_output.txt"
|
||||
configType: startup-config
|
||||
protocol: "tftp"
|
||||
serverip: "10.241.106.118"
|
||||
rcpath: "/anil/G8272-startup-config.txt"
|
||||
serverusername: "root"
|
||||
serverpassword: "root123"
|
||||
|
||||
'''
|
||||
RETURN = '''
|
||||
msg:
|
||||
description: Success or failure message
|
||||
returned: always
|
||||
type: string
|
||||
sample: "Config file tranferred to server"
|
||||
'''
|
||||
|
||||
import sys
|
||||
try:
|
||||
import paramiko
|
||||
HAS_PARAMIKO = True
|
||||
except ImportError:
|
||||
HAS_PARAMIKO = False
|
||||
import time
|
||||
import socket
|
||||
import array
|
||||
import json
|
||||
import time
|
||||
import re
|
||||
try:
|
||||
from ansible.module_utils import cnos
|
||||
HAS_LIB = True
|
||||
except:
|
||||
HAS_LIB = False
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
outputfile=dict(required=True),
|
||||
host=dict(required=True),
|
||||
username=dict(required=True),
|
||||
password=dict(required=True, no_log=True),
|
||||
enablePassword=dict(required=False, no_log=True),
|
||||
deviceType=dict(required=True),
|
||||
configType=dict(required=True),
|
||||
protocol=dict(required=True),
|
||||
serverip=dict(required=True),
|
||||
rcpath=dict(required=True),
|
||||
serverusername=dict(required=False),
|
||||
serverpassword=dict(required=False, no_log=True),),
|
||||
supports_check_mode=False)
|
||||
|
||||
username = module.params['username']
|
||||
password = module.params['password']
|
||||
enablePassword = module.params['enablePassword']
|
||||
outputfile = module.params['outputfile']
|
||||
host = module.params['host']
|
||||
deviceType = module.params['deviceType']
|
||||
configType = module.params['configType']
|
||||
protocol = module.params['protocol'].lower()
|
||||
rcserverip = module.params['serverip']
|
||||
rcpath = module.params['rcpath']
|
||||
serveruser = module.params['serverusername']
|
||||
serverpwd = module.params['serverpassword']
|
||||
output = ""
|
||||
timeout = 90
|
||||
tftptimeout = 450
|
||||
|
||||
if not HAS_PARAMIKO:
|
||||
module.fail_json(msg='paramiko is required for this module')
|
||||
|
||||
# Create instance of SSHClient object
|
||||
remote_conn_pre = paramiko.SSHClient()
|
||||
|
||||
# Automatically add untrusted hosts (make sure okay for security policy in
|
||||
# your environment)
|
||||
remote_conn_pre.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
|
||||
# initiate SSH connection with the switch
|
||||
remote_conn_pre.connect(host, username=username, password=password)
|
||||
time.sleep(2)
|
||||
|
||||
# Use invoke_shell to establish an 'interactive session'
|
||||
remote_conn = remote_conn_pre.invoke_shell()
|
||||
time.sleep(2)
|
||||
|
||||
#
|
||||
# Enable and enter configure terminal then send command
|
||||
output = output + cnos.waitForDeviceResponse("\n", ">", 2, remote_conn)
|
||||
|
||||
output = output + \
|
||||
cnos.enterEnableModeForDevice(enablePassword, 3, remote_conn)
|
||||
|
||||
# Make terminal length = 0
|
||||
output = output + \
|
||||
cnos.waitForDeviceResponse("terminal length 0\n", "#", 2, remote_conn)
|
||||
|
||||
# Invoke method for config transfer from server
|
||||
if(configType == 'running-config'):
|
||||
if(protocol == "tftp" or protocol == "ftp"):
|
||||
transfer_status = cnos.doRunningConfigBackUp(
|
||||
protocol, tftptimeout, rcserverip, rcpath, serveruser,
|
||||
serverpwd, remote_conn)
|
||||
elif(protocol == "sftp" or protocol == "scp"):
|
||||
transfer_status = cnos.doSecureRunningConfigBackUp(
|
||||
protocol, timeout, rcserverip, rcpath, serveruser,
|
||||
serverpwd, remote_conn)
|
||||
else:
|
||||
transfer_status = "Invalid Protocol option"
|
||||
elif(configType == 'startup-config'):
|
||||
if(protocol == "tftp" or protocol == "ftp"):
|
||||
transfer_status = cnos.doStartupConfigBackUp(
|
||||
protocol, tftptimeout, rcserverip, rcpath, serveruser,
|
||||
serverpwd, remote_conn)
|
||||
elif(protocol == "sftp" or protocol == "scp"):
|
||||
transfer_status = cnos.doSecureStartupConfigBackUp(
|
||||
protocol, timeout, rcserverip, rcpath, serveruser, serverpwd,
|
||||
remote_conn)
|
||||
else:
|
||||
transfer_status = "Invalid Protocol option"
|
||||
else:
|
||||
transfer_status = "Invalid configType Option"
|
||||
|
||||
output = output + "\n Config Back Up status \n" + transfer_status
|
||||
|
||||
# Save it into the file
|
||||
file = open(outputfile, "a")
|
||||
file.write(output)
|
||||
file.close()
|
||||
|
||||
# Logic to check when changes occur or not
|
||||
errorMsg = cnos.checkOutputForError(output)
|
||||
if(errorMsg is None):
|
||||
module.exit_json(changed=True, msg="Config file tranferred to server")
|
||||
else:
|
||||
module.fail_json(msg=errorMsg)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
472
lib/ansible/modules/network/cnos/cnos_bgp.py
Normal file
472
lib/ansible/modules/network/cnos/cnos_bgp.py
Normal file
@@ -0,0 +1,472 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
#
|
||||
# Copyright (C) 2017 Lenovo, 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/>.
|
||||
#
|
||||
# Module to send BGP commands to Lenovo Switches
|
||||
# Lenovo Networking
|
||||
#
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: cnos_bgp
|
||||
author: "Dave Kasberg (@dkasberg)"
|
||||
short_description: Manage BGP resources and attributes on devices running Lenovo CNOS
|
||||
description:
|
||||
- This module allows you to work with Border Gateway Protocol (BGP) related configurations.
|
||||
The operators used are overloaded to ensure control over switch BGP configurations. This
|
||||
module is invoked using method with asNumber as one of its arguments. The first level of
|
||||
the BGP configuration allows to set up an AS number, with the following attributes going
|
||||
into various configuration operations under the context of BGP. After passing this level,
|
||||
there are eight BGP arguments that will perform further configurations. They are bgpArg1,
|
||||
bgpArg2, bgpArg3, bgpArg4, bgpArg5, bgpArg6, bgpArg7, and bgpArg8. For more details on
|
||||
how to use these arguments, see [Overloaded Variables].
|
||||
This module uses SSH to manage network device configuration.
|
||||
The results of the operation will be placed in a directory named 'results'
|
||||
that must be created by the user in their local directory to where the playbook is run.
|
||||
For more information about this module from Lenovo and customizing it usage for your
|
||||
use cases, please visit U(http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_bgp.html)
|
||||
version_added: "2.3"
|
||||
extends_documentation_fragment: cnos
|
||||
options:
|
||||
asNum:
|
||||
description:
|
||||
- AS number
|
||||
required: Yes
|
||||
default: Null
|
||||
bgpArg1:
|
||||
description:
|
||||
- This is an overloaded bgp first argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: Yes
|
||||
default: Null
|
||||
choices: [address-family,bestpath,bgp,cluster-id,confederation,enforce-first-as,fast-external-failover,
|
||||
graceful-restart,graceful-restart-helper,log-neighbor-changes,maxas-limit,neighbor,router-id,shutdown,
|
||||
synchronization,timers,vrf]
|
||||
bgpArg2:
|
||||
description:
|
||||
- This is an overloaded bgp second argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: No
|
||||
default: Null
|
||||
choices: [ipv4 or ipv6, always-compare-med,compare-confed-aspath,compare-routerid,dont-compare-originator-id,tie-break-on-age,
|
||||
as-path,med,identifier,peers]
|
||||
bgpArg3:
|
||||
description:
|
||||
- This is an overloaded bgp third argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: No
|
||||
default: Null
|
||||
choices: [aggregate-address,client-to-client,dampening,distance,maximum-paths,network,nexthop,redistribute,save,synchronization,
|
||||
ignore or multipath-relax, confed or missing-as-worst or non-deterministic or remove-recv-med or remove-send-med]
|
||||
bgpArg4:
|
||||
description:
|
||||
- This is an overloaded bgp fourth argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: No
|
||||
default: Null
|
||||
choices: [Aggregate prefix, Reachability Half-life time,route-map, Distance for routes external,ebgp or ibgp,
|
||||
IP prefix <network>,IP prefix <network>/<length>, synchronization, Delay value, direct, ospf, static, memory]
|
||||
bgpArg5:
|
||||
description:
|
||||
- This is an overloaded bgp fifth argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: No
|
||||
default: Null
|
||||
choices: [as-set, summary-only, Value to start reusing a route, Distance for routes internal, Supported multipath numbers,
|
||||
backdoor, map, route-map ]
|
||||
bgpArg6:
|
||||
description:
|
||||
- This is an overloaded bgp sixth argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: No
|
||||
default: Null
|
||||
choices: [summary-only,as-set, route-map name, Value to start suppressing a route, Distance for local routes, Network mask,
|
||||
Pointer to route-map entries]
|
||||
bgpArg7:
|
||||
description:
|
||||
- This is an overloaded bgp seventh argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: No
|
||||
default: Null
|
||||
choices: [ Maximum duration to suppress a stable route(minutes), backdoor,route-map, Name of the route map ]
|
||||
bgpArg8:
|
||||
description:
|
||||
- This is an overloaded bgp eigth argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: No
|
||||
default: Null
|
||||
choices: [ Un-reachability Half-life time for the penalty(minutes), backdoor]
|
||||
'''
|
||||
EXAMPLES = '''
|
||||
Tasks: The following are examples of using the module cnos_bgp. These are written in the main.yml file of the tasks directory.
|
||||
---
|
||||
- name: Test BGP - neighbor
|
||||
cnos_bgp:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
|
||||
asNum: 33
|
||||
bgpArg1: "neighbor"
|
||||
bgpArg2: "10.241.107.40"
|
||||
bgpArg3: 13
|
||||
bgpArg4: "address-family"
|
||||
bgpArg5: "ipv4"
|
||||
bgpArg6: "next-hop-self"
|
||||
|
||||
- name: Test BGP - BFD
|
||||
cnos_bgp:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
|
||||
asNum: 33
|
||||
bgpArg1: "neighbor"
|
||||
bgpArg2: "10.241.107.40"
|
||||
bgpArg3: 13
|
||||
bgpArg4: "bfd"
|
||||
|
||||
- name: Test BGP - address-family - dampening
|
||||
cnos_bgp:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
|
||||
asNum: 33
|
||||
bgpArg1: "address-family"
|
||||
bgpArg2: "ipv4"
|
||||
bgpArg3: "dampening"
|
||||
bgpArg4: 13
|
||||
bgpArg5: 233
|
||||
bgpArg6: 333
|
||||
bgpArg7: 15
|
||||
bgpArg8: 33
|
||||
|
||||
- name: Test BGP - address-family - network
|
||||
cnos_bgp:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
|
||||
asNum: 33
|
||||
bgpArg1: "address-family"
|
||||
bgpArg2: "ipv4"
|
||||
bgpArg3: "network"
|
||||
bgpArg4: "1.2.3.4/5"
|
||||
bgpArg5: "backdoor"
|
||||
|
||||
- name: Test BGP - bestpath - always-compare-med
|
||||
cnos_bgp:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
|
||||
asNum: 33
|
||||
bgpArg1: "bestpath"
|
||||
bgpArg2: "always-compare-med"
|
||||
|
||||
- name: Test BGP - bestpath-compare-confed-aspat
|
||||
cnos_bgp:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
|
||||
asNum: 33
|
||||
bgpArg1: "bestpath"
|
||||
bgpArg2: "compare-confed-aspath"
|
||||
|
||||
- name: Test BGP - bgp
|
||||
cnos_bgp:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
|
||||
asNum: 33
|
||||
bgpArg1: "bgp"
|
||||
bgpArg2: 33
|
||||
|
||||
- name: Test BGP - cluster-id
|
||||
cnos_bgp:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
|
||||
asNum: 33
|
||||
bgpArg1: "cluster-id"
|
||||
bgpArg2: "1.2.3.4"
|
||||
|
||||
- name: Test BGP - confederation-identifier
|
||||
cnos_bgp:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
|
||||
asNum: 33
|
||||
bgpArg1: "confederation"
|
||||
bgpArg2: "identifier"
|
||||
bgpArg3: 333
|
||||
|
||||
- name: Test BGP - enforce-first-as
|
||||
cnos_bgp:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
|
||||
asNum: 33
|
||||
bgpArg1: "enforce-first-as"
|
||||
|
||||
- name: Test BGP - fast-external-failover
|
||||
cnos_bgp:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
|
||||
asNum: 33
|
||||
bgpArg1: "fast-external-failover"
|
||||
|
||||
- name: Test BGP - graceful-restart
|
||||
cnos_bgp:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
|
||||
asNum: 33
|
||||
bgpArg1: "graceful-restart"
|
||||
bgpArg2: 333
|
||||
|
||||
- name: Test BGP - graceful-restart-helper
|
||||
cnos_bgp:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
|
||||
asNum: 33
|
||||
bgpArg1: "graceful-restart-helper"
|
||||
|
||||
- name: Test BGP - maxas-limit
|
||||
cnos_bgp:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
|
||||
asNum: 33
|
||||
bgpArg1: "maxas-limit"
|
||||
bgpArg2: 333
|
||||
|
||||
- name: Test BGP - neighbor
|
||||
cnos_bgp:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
|
||||
asNum: 33
|
||||
bgpArg1: "neighbor"
|
||||
bgpArg2: "10.241.107.40"
|
||||
bgpArg3: 13
|
||||
bgpArg4: "address-family"
|
||||
bgpArg5: "ipv4"
|
||||
bgpArg6: "next-hop-self"
|
||||
|
||||
- name: Test BGP - router-id
|
||||
cnos_bgp:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
|
||||
asNum: 33
|
||||
bgpArg1: "router-id"
|
||||
bgpArg2: "1.2.3.4"
|
||||
|
||||
- name: Test BGP - synchronization
|
||||
cnos_bgp:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
|
||||
asNum: 33
|
||||
bgpArg1: "synchronization"
|
||||
|
||||
- name: Test BGP - timers
|
||||
cnos_bgp:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
|
||||
asNum: 33
|
||||
bgpArg1: "timers"
|
||||
bgpArg2: 333
|
||||
bgpArg3: 3333
|
||||
|
||||
- name: Test BGP - vrf
|
||||
cnos_bgp:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_bgp_{{ inventory_hostname }}_output.txt"
|
||||
asNum: 33
|
||||
bgpArg1: "vrf"
|
||||
|
||||
'''
|
||||
RETURN = '''
|
||||
msg:
|
||||
description: Success or failure message. Upon any failure, the method returns an error display string.
|
||||
returned: always
|
||||
type: string
|
||||
'''
|
||||
|
||||
import sys
|
||||
try:
|
||||
import paramiko
|
||||
HAS_PARAMIKO = True
|
||||
except ImportError:
|
||||
HAS_PARAMIKO = False
|
||||
import time
|
||||
import socket
|
||||
import array
|
||||
import json
|
||||
import time
|
||||
import re
|
||||
try:
|
||||
from ansible.module_utils import cnos
|
||||
HAS_LIB = True
|
||||
except:
|
||||
HAS_LIB = False
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
outputfile=dict(required=True),
|
||||
host=dict(required=True),
|
||||
username=dict(required=True),
|
||||
password=dict(required=True, no_log=True),
|
||||
enablePassword=dict(required=False, no_log=True),
|
||||
deviceType=dict(required=True),
|
||||
bgpArg1=dict(required=True),
|
||||
bgpArg2=dict(required=False),
|
||||
bgpArg3=dict(required=False),
|
||||
bgpArg4=dict(required=False),
|
||||
bgpArg5=dict(required=False),
|
||||
bgpArg6=dict(required=False),
|
||||
bgpArg7=dict(required=False),
|
||||
bgpArg8=dict(required=False),
|
||||
asNum=dict(required=True),),
|
||||
supports_check_mode=False)
|
||||
|
||||
username = module.params['username']
|
||||
password = module.params['password']
|
||||
enablePassword = module.params['enablePassword']
|
||||
bgpArg1 = module.params['bgpArg1']
|
||||
bgpArg2 = module.params['bgpArg2']
|
||||
bgpArg3 = module.params['bgpArg3']
|
||||
bgpArg4 = module.params['bgpArg4']
|
||||
bgpArg5 = module.params['bgpArg5']
|
||||
bgpArg6 = module.params['bgpArg6']
|
||||
bgpArg7 = module.params['bgpArg7']
|
||||
bgpArg8 = module.params['bgpArg8']
|
||||
asNum = module.params['asNum']
|
||||
outputfile = module.params['outputfile']
|
||||
hostIP = module.params['host']
|
||||
deviceType = module.params['deviceType']
|
||||
output = ""
|
||||
|
||||
if not HAS_PARAMIKO:
|
||||
module.fail_json(msg='paramiko is required for this module')
|
||||
# Create instance of SSHClient object
|
||||
remote_conn_pre = paramiko.SSHClient()
|
||||
|
||||
# Automatically add untrusted hosts (make sure okay for security policy in your environment)
|
||||
remote_conn_pre.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
|
||||
# initiate SSH connection with the switch
|
||||
remote_conn_pre.connect(hostIP, username=username, password=password)
|
||||
time.sleep(2)
|
||||
|
||||
# Use invoke_shell to establish an 'interactive session'
|
||||
remote_conn = remote_conn_pre.invoke_shell()
|
||||
time.sleep(2)
|
||||
|
||||
# Enable and enter configure terminal then send command
|
||||
output = output + cnos.waitForDeviceResponse("\n", ">", 2, remote_conn)
|
||||
|
||||
output = output + cnos.enterEnableModeForDevice(enablePassword, 3, remote_conn)
|
||||
|
||||
# Make terminal length = 0
|
||||
output = output + cnos.waitForDeviceResponse("terminal length 0\n", "#", 2, remote_conn)
|
||||
|
||||
# Go to config mode
|
||||
output = output + cnos.waitForDeviceResponse("configure d\n", "(config)#", 2, remote_conn)
|
||||
|
||||
# Send the CLi command
|
||||
output = output + cnos.routerConfig(remote_conn, deviceType, "(config)#", 2, "bgp", asNum,
|
||||
bgpArg1, bgpArg2, bgpArg3, bgpArg4, bgpArg5, bgpArg6, bgpArg7, bgpArg8)
|
||||
|
||||
# Save it into the file
|
||||
file = open(outputfile, "a")
|
||||
file.write(output)
|
||||
file.close()
|
||||
|
||||
# Logic to check when changes occur or not
|
||||
errorMsg = cnos.checkOutputForError(output)
|
||||
if(errorMsg is None):
|
||||
module.exit_json(changed=True, msg="BGP configurations accomplished")
|
||||
else:
|
||||
module.fail_json(msg=errorMsg)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
166
lib/ansible/modules/network/cnos/cnos_command.py
Normal file
166
lib/ansible/modules/network/cnos/cnos_command.py
Normal file
@@ -0,0 +1,166 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
#
|
||||
# Copyright (C) 2017 Lenovo, 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/>.
|
||||
#
|
||||
# Module to send CLI commands to Lenovo Switches
|
||||
# Lenovo Networking
|
||||
#
|
||||
#
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: cnos_command
|
||||
author: "Dave Kasberg (@dkasberg)"
|
||||
short_description: Execute a single command on devices running Lenovo CNOS
|
||||
description:
|
||||
- This module allows you to modify the switch running configuration. It provides a way to
|
||||
execute a single CNOS command on a switch by evaluating the current running configuration
|
||||
and executing the command only if the specific setting has not been already configured.
|
||||
The CNOS command is passed as an argument of the method.
|
||||
This module uses SSH to manage network device configuration.
|
||||
The results of the operation will be placed in a directory named 'results'
|
||||
that must be created by the user in their local directory to where the playbook is run.
|
||||
For more information about this module from Lenovo and customizing it usage for your
|
||||
use cases, please visit U(http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_command.html)
|
||||
version_added: "2.3"
|
||||
extends_documentation_fragment: cnos
|
||||
options:
|
||||
clicommand:
|
||||
description:
|
||||
- This specifies the CLI command as an attribute to this method. The command is
|
||||
passed using double quotes. The variables can be placed directly on to the CLI
|
||||
commands or can be invoked from the vars directory.
|
||||
required: true
|
||||
default: Null
|
||||
'''
|
||||
EXAMPLES = '''
|
||||
Tasks : The following are examples of using the module cnos_command. These are written in the main.yml file of the tasks directory.
|
||||
---
|
||||
- name: Test Command
|
||||
cnos_command:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
outputfile: "./results/test_command_{{ inventory_hostname }}_output.txt"
|
||||
clicommand: "display users"
|
||||
|
||||
'''
|
||||
RETURN = '''
|
||||
msg:
|
||||
description: Success or failure message
|
||||
returned: always
|
||||
type: string
|
||||
sample: "Command Applied"
|
||||
'''
|
||||
|
||||
import sys
|
||||
try:
|
||||
import paramiko
|
||||
HAS_PARAMIKO = True
|
||||
except ImportError:
|
||||
HAS_PARAMIKO = False
|
||||
import time
|
||||
import socket
|
||||
import array
|
||||
import json
|
||||
import time
|
||||
import re
|
||||
try:
|
||||
from ansible.module_utils import cnos
|
||||
HAS_LIB = True
|
||||
except:
|
||||
HAS_LIB = False
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
clicommand=dict(required=True),
|
||||
outputfile=dict(required=True),
|
||||
host=dict(required=True),
|
||||
deviceType=dict(required=True),
|
||||
username=dict(required=True),
|
||||
password=dict(required=True, no_log=True),
|
||||
enablePassword=dict(required=False, no_log=True),),
|
||||
supports_check_mode=False)
|
||||
|
||||
username = module.params['username']
|
||||
password = module.params['password']
|
||||
enablePassword = module.params['enablePassword']
|
||||
cliCommand = module.params['clicommand']
|
||||
deviceType = module.params['deviceType']
|
||||
outputfile = module.params['outputfile']
|
||||
hostIP = module.params['host']
|
||||
output = ""
|
||||
if not HAS_PARAMIKO:
|
||||
module.fail_json(msg='paramiko is required for this module')
|
||||
|
||||
# Create instance of SSHClient object
|
||||
remote_conn_pre = paramiko.SSHClient()
|
||||
|
||||
# Automatically add untrusted hosts (make sure okay for security policy in your environment)
|
||||
remote_conn_pre.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
|
||||
# initiate SSH connection with the switch
|
||||
remote_conn_pre.connect(hostIP, username=username, password=password)
|
||||
time.sleep(2)
|
||||
|
||||
# Use invoke_shell to establish an 'interactive session'
|
||||
remote_conn = remote_conn_pre.invoke_shell()
|
||||
time.sleep(2)
|
||||
|
||||
# Enable and enter configure terminal then send command
|
||||
output = output + cnos.waitForDeviceResponse("\n", ">", 2, remote_conn)
|
||||
|
||||
output = output + cnos.enterEnableModeForDevice(enablePassword, 3, remote_conn)
|
||||
|
||||
# Make terminal length = 0
|
||||
output = output + cnos.waitForDeviceResponse("terminal length 0\n", "#", 2, remote_conn)
|
||||
|
||||
# Go to config mode
|
||||
output = output + cnos.waitForDeviceResponse("configure d\n", "(config)#", 2, remote_conn)
|
||||
|
||||
# Send the CLi command
|
||||
output = output + cnos.waitForDeviceResponse(cliCommand + "\n", "(config)#", 2, remote_conn)
|
||||
|
||||
# Save it into the file
|
||||
file = open(outputfile, "a")
|
||||
file.write(output)
|
||||
file.close()
|
||||
|
||||
# Logic to check when changes occur or not
|
||||
errorMsg = cnos.checkOutputForError(output)
|
||||
if(errorMsg is None):
|
||||
module.exit_json(changed=True, msg="CLI command executed and results saved in file ")
|
||||
else:
|
||||
module.fail_json(msg=errorMsg)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
193
lib/ansible/modules/network/cnos/cnos_conditional_command.py
Normal file
193
lib/ansible/modules/network/cnos/cnos_conditional_command.py
Normal file
@@ -0,0 +1,193 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
#
|
||||
# Copyright (C) 2017 Lenovo, 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/>.
|
||||
#
|
||||
# Module to send Conditional CLI commands to Lenovo Switches
|
||||
# Lenovo Networking
|
||||
#
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: cnos_conditional_command
|
||||
author: "Dave Kasberg (@dkasberg)"
|
||||
short_description: Execute a single command based on condition on devices running Lenovo CNOS
|
||||
description:
|
||||
- This module allows you to modify the running configuration of a switch. It provides a way to
|
||||
execute a single CNOS command on a network device by evaluating the current running configuration
|
||||
and executing the command only if the specific settings have not been already configured.
|
||||
The CNOS command is passed as an argument of the method.
|
||||
This module functions the same as the cnos_command module.
|
||||
The only exception is that the following inventory variable can be specified
|
||||
["condition = <flag string>"]
|
||||
When this inventory variable is specified as the variable of a task, the command is executed for
|
||||
the network element that matches the flag string. Usually, commands are executed across a group
|
||||
of network devices. When there is a requirement to skip the execution of the command on one or
|
||||
more devices, it is recommended to use this module.
|
||||
This module uses SSH to manage network device configuration.
|
||||
For more information about this module from Lenovo and customizing it usage for your
|
||||
use cases, please visit U(http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_conditional_command.html)
|
||||
version_added: "2.3"
|
||||
extends_documentation_fragment: cnos
|
||||
options:
|
||||
clicommand:
|
||||
description:
|
||||
- This specifies the CLI command as an attribute to this method. The command is passed using
|
||||
double quotes. The variables can be placed directly on to the CLI commands or can be invoked
|
||||
from the vars directory.
|
||||
required: true
|
||||
default: Null
|
||||
condition:
|
||||
description:
|
||||
- If you specify condition=false in the inventory file against any device, the command execution
|
||||
is skipped for that device.
|
||||
required: true
|
||||
default: Null
|
||||
flag:
|
||||
description:
|
||||
- If a task needs to be executed, you have to set the flag the same as it is specified in the
|
||||
inventory for that device.
|
||||
required: true
|
||||
default: Null
|
||||
|
||||
'''
|
||||
EXAMPLES = '''
|
||||
Tasks : The following are examples of using the module cnos_conditional_command. These are written in the main.yml file of the tasks directory.
|
||||
---
|
||||
- name: Applying CLI template on VLAG Tier1 Leaf Switch1
|
||||
cnos_conditional_command:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_conditional_command_{{ inventory_hostname }}_output.txt"
|
||||
condition: "{{ hostvars[inventory_hostname]['condition']}}"
|
||||
flag: leaf_switch2
|
||||
command: "spanning-tree mode enable"
|
||||
enablePassword: "anil"
|
||||
|
||||
'''
|
||||
RETURN = '''
|
||||
msg:
|
||||
description: Success or failure message
|
||||
returned: always
|
||||
type: string
|
||||
sample: "Command Applied"
|
||||
'''
|
||||
|
||||
import sys
|
||||
try:
|
||||
import paramiko
|
||||
HAS_PARAMIKO = True
|
||||
except ImportError:
|
||||
HAS_PARAMIKO = False
|
||||
import time
|
||||
import socket
|
||||
import array
|
||||
import json
|
||||
import time
|
||||
import re
|
||||
try:
|
||||
from ansible.module_utils import cnos
|
||||
HAS_LIB = True
|
||||
except:
|
||||
HAS_LIB = False
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
clicommand=dict(required=True),
|
||||
outputfile=dict(required=True),
|
||||
condition=dict(required=True),
|
||||
flag=dict(required=True),
|
||||
host=dict(required=True),
|
||||
deviceType=dict(required=True),
|
||||
username=dict(required=True),
|
||||
password=dict(required=True, no_log=True),
|
||||
enablePassword=dict(required=False, no_log=True), ), supports_check_mode=False)
|
||||
|
||||
username = module.params['username']
|
||||
password = module.params['password']
|
||||
enablePassword = module.params['enablePassword']
|
||||
condition = module.params['condition']
|
||||
flag = module.params['flag']
|
||||
cliCommand = module.params['clicommand']
|
||||
outputfile = module.params['outputfile']
|
||||
deviceType = module.params['deviceType']
|
||||
hostIP = module.params['host']
|
||||
output = ""
|
||||
if not HAS_PARAMIKO:
|
||||
module.fail_json(msg='paramiko is required for this module')
|
||||
|
||||
if (condition != flag):
|
||||
module.exit_json(changed=True, msg="Command Skipped for this value")
|
||||
return " "
|
||||
# Create instance of SSHClient object
|
||||
remote_conn_pre = paramiko.SSHClient()
|
||||
|
||||
# Automatically add untrusted hosts (make sure okay for security policy in your environment)
|
||||
remote_conn_pre.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
|
||||
# initiate SSH connection with the switch
|
||||
remote_conn_pre.connect(hostIP, username=username, password=password)
|
||||
time.sleep(2)
|
||||
|
||||
# Use invoke_shell to establish an 'interactive session'
|
||||
remote_conn = remote_conn_pre.invoke_shell()
|
||||
time.sleep(2)
|
||||
|
||||
# Enable and enter configure terminal then send command
|
||||
#
|
||||
# Enable and enter configure terminal then send command
|
||||
output = output + cnos.waitForDeviceResponse("\n", ">", 2, remote_conn)
|
||||
output = output + cnos.enterEnableModeForDevice(enablePassword, 3, remote_conn)
|
||||
|
||||
# Make terminal length = 0
|
||||
output = output + cnos.waitForDeviceResponse("terminal length 0\n", "#", 2, remote_conn)
|
||||
|
||||
# Go to config mode
|
||||
output = output + cnos.waitForDeviceResponse("configure d\n", "(config)#", 2, remote_conn)
|
||||
|
||||
# Send the CLi command
|
||||
output = output + cnos.waitForDeviceResponse(cliCommand + "\n", "(config)#", 2, remote_conn)
|
||||
|
||||
# Save it into the file
|
||||
file = open(outputfile, "a")
|
||||
file.write(output)
|
||||
file.close()
|
||||
|
||||
# Logic to check when changes occur or not
|
||||
errorMsg = cnos.checkOutputForError(output)
|
||||
if(errorMsg is None):
|
||||
module.exit_json(changed=True, msg="CLI Command executed and results saved in file ")
|
||||
else:
|
||||
module.fail_json(msg=errorMsg)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
218
lib/ansible/modules/network/cnos/cnos_conditional_template.py
Normal file
218
lib/ansible/modules/network/cnos/cnos_conditional_template.py
Normal file
@@ -0,0 +1,218 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
#
|
||||
# Copyright (C) 2017 Lenovo, 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/>.
|
||||
#
|
||||
# Module to send conditional template to Lenovo Switches
|
||||
# Lenovo Networking
|
||||
#
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: cnos_conditional_template
|
||||
author: "Dave Kasberg (@dkasberg)"
|
||||
short_description: Manage switch configuration using templates based on condition on devices running Lenovo CNOS
|
||||
description:
|
||||
- This module allows you to work with the running configuration of a switch. It provides a way to
|
||||
execute a set of CNOS commands on a switch by evaluating the current running configuration and
|
||||
executing the commands only if the specific settings have not been already configured.
|
||||
The configuration source can be a set of commands or a template written in the Jinja2 templating language.
|
||||
This module functions the same as the cnos_template module.
|
||||
The only exception is that the following inventory variable can be specified
|
||||
["condition = <flag string>"]
|
||||
When this inventory variable is specified as the variable of a task, the template is executed for
|
||||
the network element that matches the flag string. Usually, templates are used when commands are the
|
||||
same across a group of network devices. When there is a requirement to skip the execution of the
|
||||
template on one or more devices, it is recommended to use this module.
|
||||
This module uses SSH to manage network device configuration.
|
||||
For more information about this module from Lenovo and customizing it usage for your
|
||||
use cases, please visit U(http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_conditional_template.html)
|
||||
version_added: "2.3"
|
||||
extends_documentation_fragment: cnos
|
||||
options:
|
||||
commandfile:
|
||||
description:
|
||||
- This specifies the path to the CNOS command file which needs to be applied. This usually
|
||||
comes from the commands folder. Generally this file is the output of the variables applied
|
||||
on a template file. So this command is preceded by a template module.
|
||||
The command file must contain the Ansible keyword {{ inventory_hostname }} and the condition
|
||||
flag in its filename to ensure that the command file is unique for each switch and condition.
|
||||
If this is omitted, the command file will be overwritten during iteration. For example,
|
||||
commandfile=./commands/clos_leaf_bgp_{{ inventory_hostname }}_LP21_commands.txt
|
||||
required: true
|
||||
default: Null
|
||||
condition:
|
||||
description:
|
||||
- If you specify condition=<flag string> in the inventory file against any device, the template
|
||||
execution is done for that device in case it matches the flag setting for that task.
|
||||
required: true
|
||||
default: Null
|
||||
flag:
|
||||
description:
|
||||
- If a task needs to be executed, you have to set the flag the same as it is specified in
|
||||
the inventory for that device.
|
||||
required: true
|
||||
default: Null
|
||||
'''
|
||||
EXAMPLES = '''
|
||||
Tasks : The following are examples of using the module cnos_conditional_template. These are written in the main.yml file of the tasks directory.
|
||||
---
|
||||
- name: Applying CLI template on VLAG Tier1 Leaf Switch1
|
||||
cnos_conditional_template:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
outputfile: "./results/vlag_1tier_leaf_switch1_{{ inventory_hostname }}_output.txt"
|
||||
condition: "{{ hostvars[inventory_hostname]['condition']}}"
|
||||
flag: "leaf_switch1"
|
||||
commandfile: "./commands/vlag_1tier_leaf_switch1_{{ inventory_hostname }}_commands.txt"
|
||||
enablePassword: "anil"
|
||||
stp_mode1: "disable"
|
||||
port_range1: "17,18,29,30"
|
||||
portchannel_interface_number1: 1001
|
||||
portchannel_mode1: active
|
||||
slot_chassis_number1: 1/48
|
||||
switchport_mode1: trunk
|
||||
'''
|
||||
RETURN = '''
|
||||
msg:
|
||||
description: Success or failure message
|
||||
returned: always
|
||||
type: string
|
||||
sample: "Template Applied."
|
||||
'''
|
||||
|
||||
import sys
|
||||
try:
|
||||
import paramiko
|
||||
HAS_PARAMIKO = True
|
||||
except ImportError:
|
||||
HAS_PARAMIKO = False
|
||||
import time
|
||||
import socket
|
||||
import array
|
||||
import json
|
||||
import time
|
||||
import re
|
||||
try:
|
||||
from ansible.module_utils import cnos
|
||||
HAS_LIB = True
|
||||
except:
|
||||
HAS_LIB = False
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
commandfile=dict(required=True),
|
||||
outputfile=dict(required=True),
|
||||
condition=dict(required=True),
|
||||
flag=dict(required=True),
|
||||
host=dict(required=True),
|
||||
deviceType=dict(required=True),
|
||||
username=dict(required=True),
|
||||
password=dict(required=True, no_log=True),
|
||||
enablePassword=dict(required=False, no_log=True),),
|
||||
supports_check_mode=False)
|
||||
|
||||
username = module.params['username']
|
||||
password = module.params['password']
|
||||
enablePassword = module.params['enablePassword']
|
||||
condition = module.params['condition']
|
||||
flag = module.params['flag']
|
||||
commandfile = module.params['commandfile']
|
||||
deviceType = module.params['deviceType']
|
||||
outputfile = module.params['outputfile']
|
||||
hostIP = module.params['host']
|
||||
|
||||
output = ""
|
||||
if not HAS_PARAMIKO:
|
||||
module.fail_json(msg='paramiko is required for this module')
|
||||
|
||||
# Here comes the logic against which a template is
|
||||
# conditionally executed for right Network element.
|
||||
if (condition != flag):
|
||||
module.exit_json(changed=True, msg="Template Skipped for this value")
|
||||
return " "
|
||||
|
||||
# Create instance of SSHClient object
|
||||
remote_conn_pre = paramiko.SSHClient()
|
||||
|
||||
# Automatically add untrusted hosts (make sure okay for security policy in your environment)
|
||||
remote_conn_pre.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
|
||||
# initiate SSH connection with the switch
|
||||
remote_conn_pre.connect(hostIP, username=username, password=password)
|
||||
time.sleep(2)
|
||||
|
||||
# Use invoke_shell to establish an 'interactive session'
|
||||
remote_conn = remote_conn_pre.invoke_shell()
|
||||
time.sleep(2)
|
||||
# Enable and enter configure terminal then send command
|
||||
output = output + cnos.waitForDeviceResponse("\n", ">", 2, remote_conn)
|
||||
|
||||
output = output + cnos.enterEnableModeForDevice(enablePassword, 3, remote_conn)
|
||||
|
||||
# Make terminal length = 0
|
||||
output = output + cnos.waitForDeviceResponse("terminal length 0\n", "#", 2, remote_conn)
|
||||
|
||||
# Go to config mode
|
||||
output = output + cnos.waitForDeviceResponse("configure d\n", "(config)#", 2, remote_conn)
|
||||
# Send commands one by one
|
||||
# with open(commandfile, "r") as f:
|
||||
f = open(commandfile, "r")
|
||||
for line in f:
|
||||
# Omit the comment lines in template file
|
||||
if not line.startswith("#"):
|
||||
# cnos.debugOutput(line)
|
||||
command = line
|
||||
if not line.endswith("\n"):
|
||||
command = command + "\n"
|
||||
response = cnos.waitForDeviceResponse(command, "#", 2, remote_conn)
|
||||
errorMsg = cnos.checkOutputForError(response)
|
||||
output = output + response
|
||||
if(errorMsg is not None):
|
||||
break
|
||||
# To cater to Mufti case
|
||||
# Write to memory
|
||||
output = output + cnos.waitForDeviceResponse("save\n", "#", 3, remote_conn)
|
||||
|
||||
# Write output to file
|
||||
file = open(outputfile, "a")
|
||||
file.write(output)
|
||||
file.close()
|
||||
|
||||
# Logic to check when changes occur or not
|
||||
errorMsg = cnos.checkOutputForError(output)
|
||||
if(errorMsg is None):
|
||||
module.exit_json(changed=True, msg="Template Applied")
|
||||
else:
|
||||
module.fail_json(msg=errorMsg)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
153
lib/ansible/modules/network/cnos/cnos_factory.py
Normal file
153
lib/ansible/modules/network/cnos/cnos_factory.py
Normal file
@@ -0,0 +1,153 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
#
|
||||
# Copyright (C) 2017 Lenovo, 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/>.
|
||||
#
|
||||
# Module to Reset to factory settings of Lenovo Switches
|
||||
# Lenovo Networking
|
||||
#
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: cnos_factory
|
||||
author: "Dave Kasberg (@dkasberg)"
|
||||
short_description: Reset the switch's startup configuration to default (factory) on devices running Lenovo CNOS
|
||||
description:
|
||||
- This module allows you to reset a switch's startup configuration. The method provides a way to reset the
|
||||
startup configuration to its factory settings. This is helpful when you want to move the switch to another
|
||||
topology as a new network device.
|
||||
This module uses SSH to manage network device configuration.
|
||||
The results of the operation can be viewed in results directory.
|
||||
For more information about this module from Lenovo and customizing it usage for your
|
||||
use cases, please visit U(http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_factory.html)
|
||||
version_added: "2.3"
|
||||
extends_documentation_fragment: cnos
|
||||
options: {}
|
||||
|
||||
'''
|
||||
EXAMPLES = '''
|
||||
Tasks : The following are examples of using the module cnos_reload. These are written in the main.yml file of the tasks directory.
|
||||
---
|
||||
- name: Test Reset to factory
|
||||
cnos_factory:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
outputfile: "./results/test_factory_{{ inventory_hostname }}_output.txt"
|
||||
|
||||
'''
|
||||
RETURN = '''
|
||||
msg:
|
||||
description: Success or failure message
|
||||
returned: always
|
||||
type: string
|
||||
sample: "Switch Startup Config is Reset to factory settings"
|
||||
'''
|
||||
|
||||
import sys
|
||||
try:
|
||||
import paramiko
|
||||
HAS_PARAMIKO = True
|
||||
except ImportError:
|
||||
HAS_PARAMIKO = False
|
||||
import time
|
||||
import socket
|
||||
import array
|
||||
import json
|
||||
import time
|
||||
import re
|
||||
try:
|
||||
from ansible.module_utils import cnos
|
||||
HAS_LIB = True
|
||||
except:
|
||||
HAS_LIB = False
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
outputfile=dict(required=True),
|
||||
host=dict(required=True),
|
||||
username=dict(required=True),
|
||||
password=dict(required=True, no_log=True),
|
||||
enablePassword=dict(required=False, no_log=True),
|
||||
deviceType=dict(required=True),),
|
||||
supports_check_mode=False)
|
||||
|
||||
username = module.params['username']
|
||||
password = module.params['password']
|
||||
enablePassword = module.params['enablePassword']
|
||||
cliCommand = "save erase \n"
|
||||
outputfile = module.params['outputfile']
|
||||
hostIP = module.params['host']
|
||||
deviceType = module.params['deviceType']
|
||||
output = ""
|
||||
if not HAS_PARAMIKO:
|
||||
module.fail_json(msg='paramiko is required for this module')
|
||||
|
||||
# Create instance of SSHClient object
|
||||
remote_conn_pre = paramiko.SSHClient()
|
||||
|
||||
# Automatically add untrusted hosts (make sure okay for security policy in your environment)
|
||||
remote_conn_pre.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
|
||||
# initiate SSH connection with the switch
|
||||
remote_conn_pre.connect(hostIP, username=username, password=password)
|
||||
time.sleep(2)
|
||||
|
||||
# Use invoke_shell to establish an 'interactive session'
|
||||
remote_conn = remote_conn_pre.invoke_shell()
|
||||
time.sleep(2)
|
||||
|
||||
# Enable and enter configure terminal then send command
|
||||
output = output + cnos.waitForDeviceResponse("\n", ">", 2, remote_conn)
|
||||
|
||||
output = output + cnos.enterEnableModeForDevice(enablePassword, 3, remote_conn)
|
||||
|
||||
# Make terminal length = 0
|
||||
output = output + cnos.waitForDeviceResponse("terminal length 0\n", "#", 2, remote_conn)
|
||||
|
||||
# cnos.debugOutput(cliCommand)
|
||||
# Send the CLi command
|
||||
output = output + cnos.waitForDeviceResponse(cliCommand, "[n]", 2, remote_conn)
|
||||
|
||||
output = output + cnos.waitForDeviceResponse("y" + "\n", "#", 2, remote_conn)
|
||||
|
||||
# Save it into the file
|
||||
file = open(outputfile, "a")
|
||||
file.write(output)
|
||||
file.close()
|
||||
|
||||
errorMsg = cnos.checkOutputForError(output)
|
||||
if(errorMsg is None):
|
||||
module.exit_json(changed=True, msg="Switch Startup Config is Reset to factory settings ")
|
||||
else:
|
||||
module.fail_json(msg=errorMsg)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
146
lib/ansible/modules/network/cnos/cnos_facts.py
Normal file
146
lib/ansible/modules/network/cnos/cnos_facts.py
Normal file
@@ -0,0 +1,146 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
#
|
||||
# Copyright (C) 2017 Lenovo, 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/>.
|
||||
#
|
||||
# Module to show sys info of Lenovo Switches
|
||||
# Lenovo Networking
|
||||
#
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: cnos_facts
|
||||
author: "Dave Kasberg (@dkasberg)"
|
||||
short_description: Collect facts on devices running Lenovo CNOS
|
||||
description:
|
||||
- This module allows you to view the switch information. It executes the show sysinfo CLI command on a switch
|
||||
and returns a file containing all the system information of the target network device. This module uses SSH to
|
||||
manage network device configuration. The results of the operation can be viewed in results directory.
|
||||
For more information about this module from Lenovo and customizing it usage for your
|
||||
use cases, please visit U(http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_facts.html)
|
||||
version_added: "2.3"
|
||||
extends_documentation_fragment: cnos
|
||||
options: {}
|
||||
|
||||
'''
|
||||
EXAMPLES = '''
|
||||
Tasks : The following are examples of using the module cnos_facts. These are written in the main.yml file of the tasks directory.
|
||||
---
|
||||
- name: Test Sys Info
|
||||
cnos_facts:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/cnos_facts_{{ inventory_hostname }}_output.txt"
|
||||
'''
|
||||
RETURN = '''
|
||||
msg:
|
||||
description: Success or failure message
|
||||
returned: always
|
||||
type: string
|
||||
sample: "Device Sys Info is saved to file"
|
||||
'''
|
||||
|
||||
import sys
|
||||
try:
|
||||
import paramiko
|
||||
HAS_PARAMIKO = True
|
||||
except ImportError:
|
||||
HAS_PARAMIKO = False
|
||||
import time
|
||||
import socket
|
||||
import array
|
||||
import json
|
||||
import time
|
||||
import re
|
||||
try:
|
||||
from ansible.module_utils import cnos
|
||||
HAS_LIB = True
|
||||
except:
|
||||
HAS_LIB = False
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
outputfile=dict(required=True),
|
||||
host=dict(required=True),
|
||||
username=dict(required=True),
|
||||
password=dict(required=True, no_log=True),
|
||||
enablePassword=dict(required=False, no_log=True),),
|
||||
supports_check_mode=False)
|
||||
|
||||
username = module.params['username']
|
||||
password = module.params['password']
|
||||
enablePassword = module.params['enablePassword']
|
||||
cliCommand = "display sys-info"
|
||||
outputfile = module.params['outputfile']
|
||||
hostIP = module.params['host']
|
||||
output = ""
|
||||
if not HAS_PARAMIKO:
|
||||
module.fail_json(msg='paramiko is required for this module')
|
||||
|
||||
# Create instance of SSHClient object
|
||||
remote_conn_pre = paramiko.SSHClient()
|
||||
|
||||
# Automatically add untrusted hosts (make sure okay for security policy in your environment)
|
||||
remote_conn_pre.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
|
||||
# initiate SSH connection with the switch
|
||||
remote_conn_pre.connect(hostIP, username=username, password=password)
|
||||
time.sleep(2)
|
||||
|
||||
# Use invoke_shell to establish an 'interactive session'
|
||||
remote_conn = remote_conn_pre.invoke_shell()
|
||||
time.sleep(2)
|
||||
|
||||
# Enable and enter configure terminal then send command
|
||||
output = output + cnos.waitForDeviceResponse("\n", ">", 2, remote_conn)
|
||||
|
||||
output = output + cnos.enterEnableModeForDevice(enablePassword, 3, remote_conn)
|
||||
|
||||
# Make terminal length = 0
|
||||
output = output + cnos.waitForDeviceResponse("terminal length 0\n", "#", 2, remote_conn)
|
||||
|
||||
# Send the CLi command
|
||||
output = output + cnos.waitForDeviceResponse(cliCommand + "\n", "#", 2, remote_conn)
|
||||
|
||||
# Save it into the file
|
||||
file = open(outputfile, "a")
|
||||
file.write(output)
|
||||
file.close()
|
||||
|
||||
errorMsg = cnos.checkOutputForError(output)
|
||||
if(errorMsg is None):
|
||||
module.exit_json(changed=True, msg="Device Sys Info is saved to file ")
|
||||
else:
|
||||
module.fail_json(msg=errorMsg)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
231
lib/ansible/modules/network/cnos/cnos_image.py
Normal file
231
lib/ansible/modules/network/cnos/cnos_image.py
Normal file
@@ -0,0 +1,231 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
#
|
||||
# Copyright (C) 2017 Lenovo, 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/>.
|
||||
#
|
||||
# Module to download new image to Lenovo Switches
|
||||
# Lenovo Networking
|
||||
#
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: cnos_image
|
||||
author: "Dave Kasberg (@dkasberg)"
|
||||
short_description: Perform firmware upgrade/download from a remote server on devices running Lenovo CNOS
|
||||
description:
|
||||
- This module allows you to work with switch firmware images. It provides a way to download a firmware image
|
||||
to a network device from a remote server using FTP, SFTP, TFTP, or SCP. The first step is to create a directory
|
||||
from where the remote server can be reached. The next step is to provide the full file path of the image's
|
||||
location. Authentication details required by the remote server must be provided as well. By default, this
|
||||
method makes the newly downloaded firmware image the active image, which will be used by the switch during the
|
||||
next restart.
|
||||
This module uses SSH to manage network device configuration.
|
||||
The results of the operation will be placed in a directory named 'results'
|
||||
that must be created by the user in their local directory to where the playbook is run.
|
||||
For more information about this module from Lenovo and customizing it usage for your
|
||||
use cases, please visit U(http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_image.html)
|
||||
version_added: "2.3"
|
||||
extends_documentation_fragment: cnos
|
||||
options:
|
||||
protocol:
|
||||
description:
|
||||
- This refers to the protocol used by the network device to interact with the remote server from where
|
||||
to download the firmware image. The choices are FTP, SFTP, TFTP, or SCP. Any other protocols will
|
||||
result in error. If this parameter is not specified, there is no default value to be used.
|
||||
required: true
|
||||
default: null
|
||||
choices: [SFTP, SCP, FTP, TFTP]
|
||||
serverip:
|
||||
description:
|
||||
- This specifies the IP Address of the remote server from where the software image will be downloaded.
|
||||
required: true
|
||||
default: null
|
||||
imgpath:
|
||||
description:
|
||||
- This specifies the full file path of the image located on the remote server. In case the relative path
|
||||
is used as the variable value, the root folder for the user of the server needs to be specified.
|
||||
required: true
|
||||
default: null
|
||||
imgtype:
|
||||
description:
|
||||
- This specifies the firmware image type to be downloaded
|
||||
required: true
|
||||
default: null
|
||||
choices: [all, boot, os, onie]
|
||||
serverusername:
|
||||
description:
|
||||
- Specify the username for the server relating to the protocol used.
|
||||
required: true
|
||||
default: null
|
||||
serverpassword:
|
||||
description:
|
||||
- Specify the password for the server relating to the protocol used.
|
||||
required: false
|
||||
default: null
|
||||
'''
|
||||
EXAMPLES = '''
|
||||
Tasks : The following are examples of using the module cnos_image. These are written in the main.yml file of the tasks directory.
|
||||
---
|
||||
- name: Test Image transfer
|
||||
cnos_image:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_image_{{ inventory_hostname }}_output.txt"
|
||||
protocol: "sftp"
|
||||
serverip: "10.241.106.118"
|
||||
imgpath: "/root/cnos_images/G8272-10.1.0.112.img"
|
||||
imgtype: "os"
|
||||
serverusername: "root"
|
||||
serverpassword: "root123"
|
||||
|
||||
- name: Test Image tftp
|
||||
cnos_image:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_image_{{ inventory_hostname }}_output.txt"
|
||||
protocol: "tftp"
|
||||
serverip: "10.241.106.118"
|
||||
imgpath: "/anil/G8272-10.2.0.34.img"
|
||||
imgtype: "os"
|
||||
serverusername: "root"
|
||||
serverpassword: "root123"
|
||||
'''
|
||||
RETURN = '''
|
||||
msg:
|
||||
description: Success or failure message
|
||||
returned: always
|
||||
type: string
|
||||
sample: "Image file tranferred to device"
|
||||
'''
|
||||
|
||||
import sys
|
||||
try:
|
||||
import paramiko
|
||||
HAS_PARAMIKO = True
|
||||
except ImportError:
|
||||
HAS_PARAMIKO = False
|
||||
import time
|
||||
import socket
|
||||
import array
|
||||
import json
|
||||
import time
|
||||
import re
|
||||
try:
|
||||
from ansible.module_utils import cnos
|
||||
HAS_LIB = True
|
||||
except:
|
||||
HAS_LIB = False
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
outputfile=dict(required=True),
|
||||
host=dict(required=True),
|
||||
username=dict(required=True),
|
||||
password=dict(required=True, no_log=True),
|
||||
enablePassword=dict(required=False, no_log=True),
|
||||
deviceType=dict(required=True),
|
||||
protocol=dict(required=True),
|
||||
serverip=dict(required=True),
|
||||
imgpath=dict(required=True),
|
||||
imgtype=dict(required=True),
|
||||
serverusername=dict(required=False),
|
||||
serverpassword=dict(required=False, no_log=True),),
|
||||
supports_check_mode=False)
|
||||
|
||||
username = module.params['username']
|
||||
password = module.params['password']
|
||||
enablePassword = module.params['enablePassword']
|
||||
outputfile = module.params['outputfile']
|
||||
host = module.params['host']
|
||||
deviceType = module.params['deviceType']
|
||||
protocol = module.params['protocol'].lower()
|
||||
imgserverip = module.params['serverip']
|
||||
imgpath = module.params['imgpath']
|
||||
imgtype = module.params['imgtype']
|
||||
imgserveruser = module.params['serverusername']
|
||||
imgserverpwd = module.params['serverpassword']
|
||||
output = ""
|
||||
timeout = 120
|
||||
tftptimeout = 600
|
||||
if not HAS_PARAMIKO:
|
||||
module.fail_json(msg='paramiko is required for this module')
|
||||
|
||||
# Create instance of SSHClient object
|
||||
remote_conn_pre = paramiko.SSHClient()
|
||||
|
||||
# Automatically add untrusted hosts (make sure okay for security policy in your environment)
|
||||
remote_conn_pre.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
|
||||
# initiate SSH connection with the switch
|
||||
remote_conn_pre.connect(host, username=username, password=password)
|
||||
time.sleep(2)
|
||||
|
||||
# Use invoke_shell to establish an 'interactive session'
|
||||
remote_conn = remote_conn_pre.invoke_shell()
|
||||
time.sleep(2)
|
||||
|
||||
# Enable and enter configure terminal then send command
|
||||
output = output + cnos.waitForDeviceResponse("\n", ">", 2, remote_conn)
|
||||
|
||||
output = output + cnos.enterEnableModeForDevice(enablePassword, 3, remote_conn)
|
||||
|
||||
# Make terminal length = 0
|
||||
output = output + cnos.waitForDeviceResponse("terminal length 0\n", "#", 2, remote_conn)
|
||||
|
||||
transfer_status = ""
|
||||
# Invoke method for image transfer from server
|
||||
if(protocol == "tftp" or protocol == "ftp"):
|
||||
transfer_status = cnos.doImageTransfer(protocol, tftptimeout, imgserverip, imgpath, imgtype, imgserveruser, imgserverpwd, remote_conn)
|
||||
elif(protocol == "sftp" or protocol == "scp"):
|
||||
transfer_status = cnos.doSecureImageTransfer(protocol, timeout, imgserverip, imgpath, imgtype, imgserveruser, imgserverpwd, remote_conn)
|
||||
else:
|
||||
transfer_status = "Invalid Protocol option"
|
||||
|
||||
output = output + "\n Image Transfer status \n" + transfer_status
|
||||
|
||||
# Save it into the file
|
||||
file = open(outputfile, "a")
|
||||
file.write(output)
|
||||
file.close()
|
||||
|
||||
# Logic to check when changes occur or not
|
||||
errorMsg = cnos.checkOutputForError(output)
|
||||
if(errorMsg is None):
|
||||
module.exit_json(changed=True, msg="Image file tranferred to device")
|
||||
else:
|
||||
module.fail_json(msg=errorMsg)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
588
lib/ansible/modules/network/cnos/cnos_interface.py
Normal file
588
lib/ansible/modules/network/cnos/cnos_interface.py
Normal file
@@ -0,0 +1,588 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
#
|
||||
# Copyright (C) 2017 Lenovo, 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/>.
|
||||
#
|
||||
# Module to send Port channel commands to Lenovo Switches
|
||||
# Lenovo Networking
|
||||
#
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: cnos_interface
|
||||
author: "Dave Kasberg (@dkasberg)"
|
||||
short_description: Manage interface configuration on devices running Lenovo CNOS
|
||||
description:
|
||||
- This module allows you to work with interface related configurations. The operators used are
|
||||
overloaded to ensure control over switch interface configurations. Apart from the regular device
|
||||
connection related attributes, there are seven interface arguments that will perform further
|
||||
configurations. They are interfaceArg1, interfaceArg2, interfaceArg3, interfaceArg4, interfaceArg5,
|
||||
interfaceArg6, and interfaceArg7. For more details on how to use these arguments, see
|
||||
[Overloaded Variables]. Interface configurations are taken care at six contexts in a regular CLI.
|
||||
They are
|
||||
1. Interface Name - Configurations
|
||||
2. Ethernet Interface - Configurations
|
||||
3. Loopback Interface Configurations
|
||||
4. Management Interface Configurations
|
||||
5. Port Aggregation - Configurations
|
||||
6. VLAN Configurations
|
||||
This module uses SSH to manage network device configuration.
|
||||
The results of the operation will be placed in a directory named 'results'
|
||||
that must be created by the user in their local directory to where the playbook is run.
|
||||
For more information about this module from Lenovo and customizing it usage for your
|
||||
use cases, please visit U(http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_interface.html)
|
||||
version_added: "2.3"
|
||||
extends_documentation_fragment: cnos
|
||||
options:
|
||||
interfaceRange:
|
||||
description:
|
||||
- This specifies the interface range in which the port aggregation is envisaged
|
||||
required: Yes
|
||||
default: Null
|
||||
interfaceOption:
|
||||
description:
|
||||
- This specifies the attribute you specify subsequent to interface command
|
||||
required: Yes
|
||||
default: Null
|
||||
choices: [None, ethernet, loopback, mgmt, port-aggregation, vlan]
|
||||
interfaceArg1:
|
||||
description:
|
||||
- This is an overloaded interface first argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: Yes
|
||||
default: Null
|
||||
choices: [aggregation-group, bfd, bridgeport, description, duplex, flowcontrol, ip, ipv6, lacp, lldp,
|
||||
load-interval, mac, mac-address, mac-learn, microburst-detection, mtu, service, service-policy,
|
||||
shutdown, snmp, spanning-tree, speed, storm-control, vlan, vrrp, port-aggregation]
|
||||
interfaceArg2:
|
||||
description:
|
||||
- This is an overloaded interface second argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: No
|
||||
default: Null
|
||||
choices: [aggregation-group number, access or mode or trunk, description, auto or full or half,
|
||||
receive or send, port-priority, suspend-individual, timeout, receive or transmit or trap-notification,
|
||||
tlv-select, Load interval delay in seconds, counter, Name for the MAC Access List, mac-address in HHHH.HHHH.HHHH format,
|
||||
THRESHOLD Value in unit of buffer cell, <64-9216> MTU in bytes-<64-9216> for L2 packet,<576-9216> for L3 IPv4 packet,
|
||||
<1280-9216> for L3 IPv6 packet, enter the instance id, input or output, copp-system-policy,
|
||||
type, 1000 or 10000 or 40000 or auto, broadcast or multicast or unicast, disable or enable or egress-only,
|
||||
Virtual router identifier, destination-ip or destination-mac or destination-port or source-dest-ip or
|
||||
source-dest-mac or source-dest-port or source-interface or source-ip or source-mac or source-port]
|
||||
interfaceArg3:
|
||||
description:
|
||||
- This is an overloaded interface third argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: No
|
||||
default: Null
|
||||
choices: [active or on or passive, on or off, LACP port priority, long or short, link-aggregation or
|
||||
mac-phy-status or management-address or max-frame-size or port-description or port-protocol-vlan or
|
||||
port-vlan or power-mdi or protocol-identity or system-capabilities or system-description or system-name
|
||||
or vid-management or vlan-name, counter for load interval, policy input name, all or Copp class name to attach,
|
||||
qos, queueing, Enter the allowed traffic level, ipv6]
|
||||
interfaceArg4:
|
||||
description:
|
||||
- This is an overloaded interface fourth argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: No
|
||||
default: Null
|
||||
choices: [key-chain, key-id, keyed-md5 or keyed-sha1 or meticulous-keyed-md5 or meticulous-keyed-sha1 or simple, Interval value in milliseconds,
|
||||
Destination IP (Both IPV4 and IPV6),in or out, MAC address, Time-out value in seconds, class-id, request, Specify the IPv4 address,
|
||||
OSPF area ID as a decimal value, OSPF area ID in IP address format, anycast or secondary, ethernet, vlan,
|
||||
MAC (hardware) address in HHHH.HHHH.HHHH format,
|
||||
Load interval delay in seconds, Specify policy input name, input or output, cost, port-priority, BFD minimum receive interval,source-interface]
|
||||
interfaceArg5:
|
||||
description:
|
||||
- This is an overloaded interface fifth argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: No
|
||||
default: Null
|
||||
choices: [name of key-chain, key-Id Value, key-chain , key-id, BFD minimum receive interval, Value of Hello Multiplier,
|
||||
admin-down or multihop or non-persistent, Vendor class-identifier name, bootfile-name or host-name or log-server or ntp-server or tftp-server-name,
|
||||
Slot/chassis number, Vlan interface, Specify policy input name, Port path cost or auto, Port priority increments of 32]
|
||||
interfaceArg6:
|
||||
description:
|
||||
- This is an overloaded interface sixth argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: No
|
||||
default: Null
|
||||
choices: [Authentication key string, name of key-chain, key-Id Value, Value of Hello Multiplier, admin-down or non-persistent]
|
||||
interfaceArg7:
|
||||
description:
|
||||
- This is an overloaded interface seventh argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: No
|
||||
default: Null
|
||||
choices: [Authentication key string, admin-down]
|
||||
|
||||
'''
|
||||
EXAMPLES = '''
|
||||
Tasks : The following are examples of using the module cnos_interface. These are written in the main.yml file of the tasks directory.
|
||||
---
|
||||
- name: Test Interface Ethernet - aggregation-group
|
||||
cnos_interface:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_interface_{{ inventory_hostname }}_output.txt"
|
||||
interfaceOption: 'ethernet'
|
||||
interfaceRange: 1
|
||||
interfaceArg1: "aggregation-group"
|
||||
interfaceArg2: 33
|
||||
interfaceArg3: "on"
|
||||
|
||||
- name: Test Interface Ethernet - bridge-port
|
||||
cnos_interface:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_interface_{{ inventory_hostname }}_output.txt"
|
||||
interfaceOption: 'ethernet'
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "bridge-port"
|
||||
interfaceArg2: "access"
|
||||
interfaceArg3: 33
|
||||
|
||||
- name: Test Interface Ethernet - bridgeport mode
|
||||
cnos_interface:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_interface_{{ inventory_hostname }}_output.txt"
|
||||
interfaceOption: 'ethernet'
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "bridge-port"
|
||||
interfaceArg2: "mode"
|
||||
interfaceArg3: "access"
|
||||
|
||||
- name: Test Interface Ethernet - Description
|
||||
cnos_interface:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_interface_{{ inventory_hostname }}_output.txt"
|
||||
interfaceOption: 'ethernet'
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "description"
|
||||
interfaceArg2: "Hentammoo "
|
||||
|
||||
- name: Test Interface Ethernet - Duplex
|
||||
cnos_interface:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_interface_{{ inventory_hostname }}_output.txt"
|
||||
interfaceOption: 'ethernet'
|
||||
interfaceRange: 1
|
||||
interfaceArg1: "duplex"
|
||||
interfaceArg2: "auto"
|
||||
|
||||
- name: Test Interface Ethernet - flowcontrol
|
||||
cnos_interface:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_interface_{{ inventory_hostname }}_output.txt"
|
||||
interfaceOption: 'ethernet'
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "flowcontrol"
|
||||
interfaceArg2: "send"
|
||||
interfaceArg3: "off"
|
||||
|
||||
- name: Test Interface Ethernet - lacp
|
||||
cnos_interface:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_interface_{{ inventory_hostname }}_output.txt"
|
||||
interfaceOption: 'ethernet'
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "lacp"
|
||||
interfaceArg2: "port-priority"
|
||||
interfaceArg3: 33
|
||||
|
||||
- name: Test Interface Ethernet - lldp
|
||||
cnos_interface:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_interface_{{ inventory_hostname }}_output.txt"
|
||||
interfaceOption: 'ethernet'
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "lldp"
|
||||
interfaceArg2: "tlv-select"
|
||||
interfaceArg3: "max-frame-size"
|
||||
|
||||
- name: Test Interface Ethernet - load-interval
|
||||
cnos_interface:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_interface_{{ inventory_hostname }}_output.txt"
|
||||
interfaceOption: 'ethernet'
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "load-interval"
|
||||
interfaceArg2: "counter"
|
||||
interfaceArg3: 2
|
||||
interfaceArg4: 33
|
||||
|
||||
- name: Test Interface Ethernet - mac
|
||||
cnos_interface:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_interface_{{ inventory_hostname }}_output.txt"
|
||||
interfaceOption: 'ethernet'
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "mac"
|
||||
interfaceArg2: "copp-system-acl-vlag-hc"
|
||||
|
||||
- name: Test Interface Ethernet - microburst-detection
|
||||
cnos_interface:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_interface_{{ inventory_hostname }}_output.txt"
|
||||
interfaceOption: 'ethernet'
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "microburst-detection"
|
||||
interfaceArg2: 25
|
||||
|
||||
- name: Test Interface Ethernet - mtu
|
||||
cnos_interface:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_interface_{{ inventory_hostname }}_output.txt"
|
||||
interfaceOption: 'ethernet'
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "mtu"
|
||||
interfaceArg2: 66
|
||||
|
||||
- name: Test Interface Ethernet - service-policy
|
||||
cnos_interface:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_interface_{{ inventory_hostname }}_output.txt"
|
||||
interfaceOption: 'ethernet'
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "service-policy"
|
||||
interfaceArg2: "input"
|
||||
interfaceArg3: "Anil"
|
||||
|
||||
- name: Test Interface Ethernet - speed
|
||||
cnos_interface:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_interface_{{ inventory_hostname }}_output.txt"
|
||||
interfaceOption: 'ethernet'
|
||||
interfaceRange: 1
|
||||
interfaceArg1: "speed"
|
||||
interfaceArg2: "auto"
|
||||
|
||||
- name: Test Interface Ethernet - storm
|
||||
cnos_interface:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_interface_{{ inventory_hostname }}_output.txt"
|
||||
interfaceOption: 'ethernet'
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "storm-control"
|
||||
interfaceArg2: "broadcast"
|
||||
interfaceArg3: 12.5
|
||||
|
||||
- name: Test Interface Ethernet - vlan
|
||||
cnos_interface:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_interface_{{ inventory_hostname }}_output.txt"
|
||||
interfaceOption: 'ethernet'
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "vlan"
|
||||
interfaceArg2: "disable"
|
||||
|
||||
- name: Test Interface Ethernet - vrrp
|
||||
cnos_interface:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_interface_{{ inventory_hostname }}_output.txt"
|
||||
interfaceOption: 'ethernet'
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "vrrp"
|
||||
interfaceArg2: 33
|
||||
|
||||
- name: Test Interface Ethernet - spanning tree1
|
||||
cnos_interface:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_interface_{{ inventory_hostname }}_output.txt"
|
||||
interfaceOption: 'ethernet'
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "spanning-tree"
|
||||
interfaceArg2: "bpduguard"
|
||||
interfaceArg3: "enable"
|
||||
|
||||
- name: Test Interface Ethernet - spanning tree 2
|
||||
cnos_interface:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_interface_{{ inventory_hostname }}_output.txt"
|
||||
interfaceOption: 'ethernet'
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "spanning-tree"
|
||||
interfaceArg2: "mst"
|
||||
interfaceArg3: "33-35"
|
||||
interfaceArg4: "cost"
|
||||
interfaceArg5: 33
|
||||
|
||||
- name: Test Interface Ethernet - ip1
|
||||
cnos_interface:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_interface_{{ inventory_hostname }}_output.txt"
|
||||
interfaceOption: 'ethernet'
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "ip"
|
||||
interfaceArg2: "access-group"
|
||||
interfaceArg3: "anil"
|
||||
interfaceArg4: "in"
|
||||
|
||||
- name: Test Interface Ethernet - ip2
|
||||
cnos_interface:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_interface_{{ inventory_hostname }}_output.txt"
|
||||
interfaceOption: 'ethernet'
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "ip"
|
||||
interfaceArg2: "port"
|
||||
interfaceArg3: "anil"
|
||||
|
||||
- name: Test Interface Ethernet - bfd
|
||||
cnos_interface:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_interface_{{ inventory_hostname }}_output.txt"
|
||||
interfaceOption: 'ethernet'
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "bfd"
|
||||
interfaceArg2: "interval"
|
||||
interfaceArg3: 55
|
||||
interfaceArg4: 55
|
||||
interfaceArg5: 33
|
||||
|
||||
- name: Test Interface Ethernet - bfd
|
||||
cnos_interface:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_interface_{{ inventory_hostname }}_output.txt"
|
||||
interfaceOption: 'ethernet'
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "bfd"
|
||||
interfaceArg2: "ipv4"
|
||||
interfaceArg3: "authentication"
|
||||
interfaceArg4: "meticulous-keyed-md5"
|
||||
interfaceArg5: "key-chain"
|
||||
interfaceArg6: "mychain"
|
||||
|
||||
'''
|
||||
RETURN = '''
|
||||
msg:
|
||||
description: Success or failure message
|
||||
returned: always
|
||||
type: string
|
||||
sample: "Interface configurations accomplished."
|
||||
'''
|
||||
|
||||
import sys
|
||||
try:
|
||||
import paramiko
|
||||
HAS_PARAMIKO = True
|
||||
except ImportError:
|
||||
HAS_PARAMIKO = False
|
||||
import time
|
||||
import socket
|
||||
import array
|
||||
import json
|
||||
import time
|
||||
import re
|
||||
try:
|
||||
from ansible.module_utils import cnos
|
||||
HAS_LIB = True
|
||||
except:
|
||||
HAS_LIB = False
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
outputfile=dict(required=True),
|
||||
host=dict(required=True),
|
||||
username=dict(required=True),
|
||||
password=dict(required=True, no_log=True),
|
||||
enablePassword=dict(required=False, no_log=True),
|
||||
deviceType=dict(required=True),
|
||||
interfaceRange=dict(required=False),
|
||||
interfaceOption=dict(required=False),
|
||||
interfaceArg1=dict(required=True),
|
||||
interfaceArg2=dict(required=False),
|
||||
interfaceArg3=dict(required=False),
|
||||
interfaceArg4=dict(required=False),
|
||||
interfaceArg5=dict(required=False),
|
||||
interfaceArg6=dict(required=False),
|
||||
interfaceArg7=dict(required=False),),
|
||||
supports_check_mode=False)
|
||||
|
||||
username = module.params['username']
|
||||
password = module.params['password']
|
||||
enablePassword = module.params['enablePassword']
|
||||
interfaceRange = module.params['interfaceRange']
|
||||
interfaceOption = module.params['interfaceOption']
|
||||
interfaceArg1 = module.params['interfaceArg1']
|
||||
interfaceArg2 = module.params['interfaceArg2']
|
||||
interfaceArg3 = module.params['interfaceArg3']
|
||||
interfaceArg4 = module.params['interfaceArg4']
|
||||
interfaceArg5 = module.params['interfaceArg5']
|
||||
interfaceArg6 = module.params['interfaceArg6']
|
||||
interfaceArg7 = module.params['interfaceArg7']
|
||||
outputfile = module.params['outputfile']
|
||||
hostIP = module.params['host']
|
||||
deviceType = module.params['deviceType']
|
||||
|
||||
output = ""
|
||||
if not HAS_PARAMIKO:
|
||||
module.fail_json(msg='paramiko is required for this module')
|
||||
|
||||
# Create instance of SSHClient object
|
||||
remote_conn_pre = paramiko.SSHClient()
|
||||
|
||||
# Automatically add untrusted hosts (make sure okay for security policy in your environment)
|
||||
remote_conn_pre.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
|
||||
# initiate SSH connection with the switch
|
||||
remote_conn_pre.connect(hostIP, username=username, password=password)
|
||||
time.sleep(2)
|
||||
|
||||
# Use invoke_shell to establish an 'interactive session'
|
||||
remote_conn = remote_conn_pre.invoke_shell()
|
||||
time.sleep(2)
|
||||
|
||||
# Enable and enter configure terminal then send command
|
||||
output = output + cnos.waitForDeviceResponse("\n", ">", 2, remote_conn)
|
||||
|
||||
output = output + cnos.enterEnableModeForDevice(enablePassword, 3, remote_conn)
|
||||
|
||||
# Make terminal length = 0
|
||||
output = output + cnos.waitForDeviceResponse("terminal length 0\n", "#", 2, remote_conn)
|
||||
|
||||
# Go to config mode
|
||||
output = output + cnos.waitForDeviceResponse("configure d\n", "(config)#", 2, remote_conn)
|
||||
|
||||
# Send the CLi command
|
||||
if(interfaceOption is None or interfaceOption == ""):
|
||||
output = output + cnos.interfaceConfig(remote_conn, deviceType, "(config)#", 2, None, interfaceRange,
|
||||
interfaceArg1, interfaceArg2, interfaceArg3, interfaceArg4, interfaceArg5, interfaceArg6, interfaceArg7)
|
||||
elif(interfaceOption == "ethernet"):
|
||||
output = output + cnos.interfaceConfig(remote_conn, deviceType, "(config)#", 2, "ethernet", interfaceRange,
|
||||
interfaceArg1, interfaceArg2, interfaceArg3, interfaceArg4, interfaceArg5, interfaceArg6, interfaceArg7)
|
||||
elif(interfaceOption == "loopback"):
|
||||
output = output + cnos.interfaceConfig(remote_conn, deviceType, "(config)#", 2, "loopback", interfaceRange,
|
||||
interfaceArg1, interfaceArg2, interfaceArg3, interfaceArg4, interfaceArg5, interfaceArg6, interfaceArg7)
|
||||
elif(interfaceOption == "mgmt"):
|
||||
output = output + cnos.interfaceConfig(remote_conn, deviceType, "(config)#", 2, "mgmt", interfaceRange,
|
||||
interfaceArg1, interfaceArg2, interfaceArg3, interfaceArg4, interfaceArg5, interfaceArg6, interfaceArg7)
|
||||
elif(interfaceOption == "port-aggregation"):
|
||||
output = output + cnos.interfaceConfig(remote_conn, deviceType, "(config)#", 2, "port-aggregation", interfaceRange,
|
||||
interfaceArg1, interfaceArg2, interfaceArg3, interfaceArg4, interfaceArg5, interfaceArg6, interfaceArg7)
|
||||
elif(interfaceOption == "vlan"):
|
||||
output = output + cnos.interfaceConfig(remote_conn, deviceType, "(config)#", 2, "vlan", interfaceRange,
|
||||
interfaceArg1, interfaceArg2, interfaceArg3, interfaceArg4, interfaceArg5, interfaceArg6, interfaceArg7)
|
||||
else:
|
||||
output = "Invalid interface option \n"
|
||||
# Save it into the file
|
||||
file = open(outputfile, "a")
|
||||
file.write(output)
|
||||
file.close()
|
||||
|
||||
# Logic to check when changes occur or not
|
||||
errorMsg = cnos.checkOutputForError(output)
|
||||
if(errorMsg is None):
|
||||
module.exit_json(changed=True, msg="Interface Configuration is done")
|
||||
else:
|
||||
module.fail_json(msg=errorMsg)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
524
lib/ansible/modules/network/cnos/cnos_portchannel.py
Normal file
524
lib/ansible/modules/network/cnos/cnos_portchannel.py
Normal file
@@ -0,0 +1,524 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
#
|
||||
# Copyright (C) 2017 Lenovo, 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/>.
|
||||
#
|
||||
# Module to send Port channel commands to Lenovo Switches
|
||||
# Lenovo Networking
|
||||
#
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: cnos_portchannel
|
||||
author: "Dave Kasberg (@dkasberg)"
|
||||
short_description: Manage portchannel (port aggregation) configuration on devices running Lenovo CNOS
|
||||
description:
|
||||
- This module allows you to work with port aggregation related configurations. The operators
|
||||
used are overloaded to ensure control over switch port aggregation configurations. Apart
|
||||
from the regular device connection related attributes, there are five LAG arguments which are
|
||||
overloaded variables that will perform further configurations. They are interfaceArg1, interfaceArg2,
|
||||
interfaceArg3, interfaceArg4, and interfaceArg5. For more details on how to use these arguments, see
|
||||
[Overloaded Variables].
|
||||
This module uses SSH to manage network device configuration.
|
||||
The results of the operation will be placed in a directory named 'results'
|
||||
that must be created by the user in their local directory to where the playbook is run.
|
||||
For more information about this module from Lenovo and customizing it usage for your
|
||||
use cases, please U(http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_portchannel.html)
|
||||
version_added: "2.3"
|
||||
extends_documentation_fragment: cnos
|
||||
options:
|
||||
interfaceRange:
|
||||
description:
|
||||
- This specifies the interface range in which the port aggregation is envisaged
|
||||
required: Yes
|
||||
default: Null
|
||||
interfaceArg1:
|
||||
description:
|
||||
- This is an overloaded Port Channel first argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: Yes
|
||||
default: Null
|
||||
choices: [aggregation-group, bfd, bridgeport, description, duplex, flowcontrol, ip, ipv6, lacp, lldp,
|
||||
load-interval, mac, mac-address, mac-learn, microburst-detection, mtu, service, service-policy,
|
||||
shutdown, snmp, spanning-tree, speed, storm-control, vlan, vrrp, port-aggregation]
|
||||
interfaceArg2:
|
||||
description:
|
||||
- This is an overloaded Port Channel second argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: No
|
||||
default: Null
|
||||
choices: [aggregation-group number, access or mode or trunk, description, auto or full or half,
|
||||
receive or send, port-priority, suspend-individual, timeout, receive or transmit or trap-notification,
|
||||
tlv-select, Load interval delay in seconds, counter, Name for the MAC Access List, mac-address in HHHH.HHHH.HHHH format,
|
||||
THRESHOLD Value in unit of buffer cell, <64-9216> MTU in bytes-<64-9216> for L2 packet,<576-9216> for
|
||||
L3 IPv4 packet, <1280-9216> for L3 IPv6 packet, enter the instance id, input or output, copp-system-policy,
|
||||
type, 1000 or 10000 or 40000 or auto, broadcast or multicast or unicast, disable or enable or egress-only,
|
||||
Virtual router identifier, destination-ip or destination-mac or destination-port or source-dest-ip or
|
||||
source-dest-mac or source-dest-port or source-interface or source-ip or source-mac or source-port]
|
||||
interfaceArg3:
|
||||
description:
|
||||
- This is an overloaded Port Channel third argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: No
|
||||
default: Null
|
||||
choices: [active or on or passive, on or off, LACP port priority, long or short, link-aggregation or
|
||||
mac-phy-status or management-address or max-frame-size or port-description or port-protocol-vlan or
|
||||
port-vlan or power-mdi or protocol-identity or system-capabilities or system-description or system-name
|
||||
or vid-management or vlan-name, counter for load interval, policy input name, all or Copp class name to attach,
|
||||
qos, queueing, Enter the allowed traffic level, ipv6]
|
||||
interfaceArg4:
|
||||
description:
|
||||
- This is an overloaded Port Channel fourth argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: No
|
||||
default: Null
|
||||
choices: [key-chain, key-id, keyed-md5 or keyed-sha1 or meticulous-keyed-md5 or meticulous-keyed-sha1 or simple, Interval value in milliseconds,
|
||||
Destination IP (Both IPV4 and IPV6),in or out, MAC address, Time-out value in seconds, class-id, request, Specify the IPv4 address,
|
||||
OSPF area ID as a decimal value, OSPF area ID in IP address format, anycast or secondary, ethernet, vlan,
|
||||
MAC (hardware) address in HHHH.HHHH.HHHH format,
|
||||
Load interval delay in seconds, Specify policy input name, input or output, cost, port-priority, BFD minimum receive interval,source-interface]
|
||||
interfaceArg5:
|
||||
description:
|
||||
- This is an overloaded Port Channel fifth argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: No
|
||||
default: Null
|
||||
choices: [name of key-chain, key-Id Value, key-chain , key-id, BFD minimum receive interval, Value of Hello Multiplier,
|
||||
admin-down or multihop or non-persistent, Vendor class-identifier name, bootfile-name or host-name or log-server or ntp-server or tftp-server-name,
|
||||
Slot/chassis number, Vlan interface, Specify policy input name, Port path cost or auto, Port priority increments of 32]
|
||||
interfaceArg6:
|
||||
description:
|
||||
- This is an overloaded Port Channel sixth argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: No
|
||||
default: Null
|
||||
choices: [Authentication key string, name of key-chain, key-Id Value, Value of Hello Multiplier, admin-down or non-persistent]
|
||||
interfaceArg7:
|
||||
description:
|
||||
- This is an overloaded Port Channel seventh argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: No
|
||||
default: Null
|
||||
choices: [Authentication key string, admin-down]
|
||||
'''
|
||||
EXAMPLES = '''
|
||||
Tasks : The following are examples of using the module cnos_portchannel. These are written in the main.yml file of the tasks directory.
|
||||
---
|
||||
- name: Test Port Channel - aggregation-group
|
||||
cnos_portchannel:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
outputfile: "./results/test_portchannel_{{ inventory_hostname }}_output.txt"
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "aggregation-group"
|
||||
interfaceArg2: 33
|
||||
interfaceArg3: "on"
|
||||
|
||||
- name: Test Port Channel - aggregation-group - Interface Range
|
||||
cnos_portchannel:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
outputfile: "./results/test_portchannel_{{ inventory_hostname }}_output.txt"
|
||||
interfaceRange: "1/1-2"
|
||||
interfaceArg1: "aggregation-group"
|
||||
interfaceArg2: 33
|
||||
interfaceArg3: "on"
|
||||
|
||||
- name: Test Port Channel - bridge-port
|
||||
cnos_portchannel:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
outputfile: "./results/test_portchannel_{{ inventory_hostname }}_output.txt"
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "bridge-port"
|
||||
interfaceArg2: "access"
|
||||
interfaceArg3: 33
|
||||
|
||||
- name: Test Port Channel - bridgeport mode
|
||||
cnos_portchannel:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
outputfile: "./results/test_portchannel_{{ inventory_hostname }}_output.txt"
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "bridge-port"
|
||||
interfaceArg2: "mode"
|
||||
interfaceArg3: "access"
|
||||
|
||||
- name: Test Port Channel - Description
|
||||
cnos_portchannel:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
outputfile: "./results/test_portchannel_{{ inventory_hostname }}_output.txt"
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "description"
|
||||
interfaceArg2: "Hentammoo "
|
||||
|
||||
- name: Test Port Channel - Duplex
|
||||
cnos_portchannel:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
outputfile: "./results/test_portchannel_{{ inventory_hostname }}_output.txt"
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "duplex"
|
||||
interfaceArg2: "auto"
|
||||
|
||||
- name: Test Port Channel - flowcontrol
|
||||
cnos_portchannel:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
outputfile: "./results/test_portchannel_{{ inventory_hostname }}_output.txt"
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "flowcontrol"
|
||||
interfaceArg2: "send"
|
||||
interfaceArg3: "off"
|
||||
|
||||
- name: Test Port Channel - lacp
|
||||
cnos_portchannel:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
outputfile: "./results/test_portchannel_{{ inventory_hostname }}_output.txt"
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "lacp"
|
||||
interfaceArg2: "port-priority"
|
||||
interfaceArg3: 33
|
||||
|
||||
- name: Test Port Channel - lldp
|
||||
cnos_portchannel:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
outputfile: "./results/test_portchannel_{{ inventory_hostname }}_output.txt"
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "lldp"
|
||||
interfaceArg2: "tlv-select"
|
||||
interfaceArg3: "max-frame-size"
|
||||
|
||||
- name: Test Port Channel - load-interval
|
||||
cnos_portchannel:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
outputfile: "./results/test_portchannel_{{ inventory_hostname }}_output.txt"
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "load-interval"
|
||||
interfaceArg2: "counter"
|
||||
interfaceArg3: 2
|
||||
interfaceArg4: 33
|
||||
|
||||
#- name: Test Port Channel - mac
|
||||
# cnos_portchannel:
|
||||
# host: "{{ inventory_hostname }}"
|
||||
# username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
# password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
# deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
# outputfile: "./results/test_portchannel_{{ inventory_hostname }}_output.txt"
|
||||
# interfaceRange: 33,
|
||||
# interfaceArg1: "mac"
|
||||
# interfaceArg2: "copp-system-acl-vlag-hc"
|
||||
|
||||
- name: Test Port Channel - microburst-detection
|
||||
cnos_portchannel:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
outputfile: "./results/test_portchannel_{{ inventory_hostname }}_output.txt"
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "microburst-detection"
|
||||
interfaceArg2: 25
|
||||
|
||||
- name: Test Port Channel - mtu
|
||||
cnos_portchannel:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
outputfile: "./results/test_portchannel_{{ inventory_hostname }}_output.txt"
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "mtu"
|
||||
interfaceArg2: 66
|
||||
|
||||
- name: Test Port Channel - service-policy
|
||||
cnos_portchannel:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
outputfile: "./results/test_portchannel_{{ inventory_hostname }}_output.txt"
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "service-policy"
|
||||
interfaceArg2: "input"
|
||||
interfaceArg3: "Anil"
|
||||
|
||||
- name: Test Port Channel - speed
|
||||
cnos_portchannel:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
outputfile: "./results/test_portchannel_{{ inventory_hostname }}_output.txt"
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "speed"
|
||||
interfaceArg2: "auto"
|
||||
|
||||
- name: Test Port Channel - storm
|
||||
cnos_portchannel:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
outputfile: "./results/test_portchannel_{{ inventory_hostname }}_output.txt"
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "storm-control"
|
||||
interfaceArg2: "broadcast"
|
||||
interfaceArg3: 12.5
|
||||
|
||||
#- name: Test Port Channel - vlan
|
||||
# cnos_portchannel:
|
||||
# host: "{{ inventory_hostname }}"
|
||||
# username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
# password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
# deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
# outputfile: "./results/test_portchannel_{{ inventory_hostname }}_output.txt"
|
||||
# interfaceRange: 33
|
||||
# interfaceArg1: "vlan"
|
||||
# interfaceArg2: "disable"
|
||||
|
||||
- name: Test Port Channel - vrrp
|
||||
cnos_portchannel:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
outputfile: "./results/test_portchannel_{{ inventory_hostname }}_output.txt"
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "vrrp"
|
||||
interfaceArg2: 33
|
||||
|
||||
- name: Test Port Channel - spanning tree1
|
||||
cnos_portchannel:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
outputfile: "./results/test_portchannel_{{ inventory_hostname }}_output.txt"
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "spanning-tree"
|
||||
interfaceArg2: "bpduguard"
|
||||
interfaceArg3: "enable"
|
||||
|
||||
- name: Test Port Channel - spanning tree 2
|
||||
cnos_portchannel:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
outputfile: "./results/test_portchannel_{{ inventory_hostname }}_output.txt"
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "spanning-tree"
|
||||
interfaceArg2: "mst"
|
||||
interfaceArg3: "33-35"
|
||||
interfaceArg4: "cost"
|
||||
interfaceArg5: 33
|
||||
|
||||
- name: Test Port Channel - ip1
|
||||
cnos_portchannel:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
outputfile: "./results/test_portchannel_{{ inventory_hostname }}_output.txt"
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "ip"
|
||||
interfaceArg2: "access-group"
|
||||
interfaceArg3: "anil"
|
||||
interfaceArg4: "in"
|
||||
|
||||
- name: Test Port Channel - ip2
|
||||
cnos_portchannel:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
outputfile: "./results/test_portchannel_{{ inventory_hostname }}_output.txt"
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "ip"
|
||||
interfaceArg2: "port"
|
||||
interfaceArg3: "anil"
|
||||
|
||||
- name: Test Port Channel - bfd
|
||||
cnos_portchannel:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
outputfile: "./results/test_portchannel_{{ inventory_hostname }}_output.txt"
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "bfd"
|
||||
interfaceArg2: "interval"
|
||||
interfaceArg3: 55
|
||||
interfaceArg4: 55
|
||||
interfaceArg5: 33
|
||||
|
||||
- name: Test Port Channel - bfd
|
||||
cnos_portchannel:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
outputfile: "./results/test_portchannel_{{ inventory_hostname }}_output.txt"
|
||||
interfaceRange: 33
|
||||
interfaceArg1: "bfd"
|
||||
interfaceArg2: "ipv4"
|
||||
interfaceArg3: "authentication"
|
||||
interfaceArg4: "meticulous-keyed-md5"
|
||||
interfaceArg5: "key-chain"
|
||||
interfaceArg6: "mychain"
|
||||
|
||||
'''
|
||||
RETURN = '''
|
||||
msg:
|
||||
description: Success or failure message
|
||||
returned: always
|
||||
type: string
|
||||
sample: "Port Channel configurations accomplished"
|
||||
'''
|
||||
|
||||
import sys
|
||||
try:
|
||||
import paramiko
|
||||
HAS_PARAMIKO = True
|
||||
except ImportError:
|
||||
HAS_PARAMIKO = False
|
||||
import time
|
||||
import socket
|
||||
import array
|
||||
import json
|
||||
import time
|
||||
import re
|
||||
try:
|
||||
from ansible.module_utils import cnos
|
||||
HAS_LIB = True
|
||||
except:
|
||||
HAS_LIB = False
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
outputfile=dict(required=True),
|
||||
host=dict(required=True),
|
||||
username=dict(required=True),
|
||||
password=dict(required=True, no_log=True),
|
||||
enablePassword=dict(required=False, no_log=True),
|
||||
deviceType=dict(required=True),
|
||||
interfaceRange=dict(required=False),
|
||||
interfaceArg1=dict(required=True),
|
||||
interfaceArg2=dict(required=False),
|
||||
interfaceArg3=dict(required=False),
|
||||
interfaceArg4=dict(required=False),
|
||||
interfaceArg5=dict(required=False),
|
||||
interfaceArg6=dict(required=False),
|
||||
interfaceArg7=dict(required=False),),
|
||||
supports_check_mode=False)
|
||||
|
||||
username = module.params['username']
|
||||
password = module.params['password']
|
||||
enablePassword = module.params['enablePassword']
|
||||
interfaceRange = module.params['interfaceRange']
|
||||
interfaceArg1 = module.params['interfaceArg1']
|
||||
interfaceArg2 = module.params['interfaceArg2']
|
||||
interfaceArg3 = module.params['interfaceArg3']
|
||||
interfaceArg4 = module.params['interfaceArg4']
|
||||
interfaceArg5 = module.params['interfaceArg5']
|
||||
interfaceArg6 = module.params['interfaceArg6']
|
||||
interfaceArg7 = module.params['interfaceArg7']
|
||||
outputfile = module.params['outputfile']
|
||||
hostIP = module.params['host']
|
||||
deviceType = module.params['deviceType']
|
||||
output = ""
|
||||
if not HAS_PARAMIKO:
|
||||
module.fail_json(msg='paramiko is required for this module')
|
||||
|
||||
# Create instance of SSHClient object
|
||||
remote_conn_pre = paramiko.SSHClient()
|
||||
|
||||
# Automatically add untrusted hosts (make sure okay for security policy in your environment)
|
||||
remote_conn_pre.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
|
||||
# initiate SSH connection with the switch
|
||||
remote_conn_pre.connect(hostIP, username=username, password=password)
|
||||
time.sleep(2)
|
||||
|
||||
# Use invoke_shell to establish an 'interactive session'
|
||||
remote_conn = remote_conn_pre.invoke_shell()
|
||||
time.sleep(2)
|
||||
|
||||
# Enable and enter configure terminal then send command
|
||||
output = output + cnos.waitForDeviceResponse("\n", ">", 2, remote_conn)
|
||||
|
||||
output = output + cnos.enterEnableModeForDevice(enablePassword, 3, remote_conn)
|
||||
|
||||
# Make terminal length = 0
|
||||
output = output + cnos.waitForDeviceResponse("terminal length 0\n", "#", 2, remote_conn)
|
||||
|
||||
# Go to config mode
|
||||
output = output + cnos.waitForDeviceResponse("configure d\n", "(config)#", 2, remote_conn)
|
||||
|
||||
# Send the CLi command
|
||||
if(interfaceArg1 == "port-aggregation"):
|
||||
output = output + cnos.portChannelConfig(remote_conn, deviceType, "(config)#", 2, interfaceArg1,
|
||||
interfaceArg2, interfaceArg3, interfaceArg4, interfaceArg5, interfaceArg6, interfaceArg7)
|
||||
else:
|
||||
output = output + cnos.interfaceConfig(remote_conn, deviceType, "(config)#", 2, "port-aggregation", interfaceRange,
|
||||
interfaceArg1, interfaceArg2, interfaceArg3, interfaceArg4, interfaceArg5, interfaceArg6, interfaceArg7)
|
||||
|
||||
# Save it into the file
|
||||
file = open(outputfile, "a")
|
||||
file.write(output)
|
||||
file.close()
|
||||
|
||||
# Logic to check when changes occur or not
|
||||
errorMsg = cnos.checkOutputForError(output)
|
||||
if(errorMsg is None):
|
||||
module.exit_json(changed=True, msg="Port Aggregation configuration is done")
|
||||
else:
|
||||
module.fail_json(msg=errorMsg)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
152
lib/ansible/modules/network/cnos/cnos_reload.py
Normal file
152
lib/ansible/modules/network/cnos/cnos_reload.py
Normal file
@@ -0,0 +1,152 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
#
|
||||
# Copyright (C) 2017 Lenovo, 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/>.
|
||||
#
|
||||
# Module to reload Lenovo Switches
|
||||
# Lenovo Networking
|
||||
#
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: cnos_reload
|
||||
author: "Dave Kasberg (@dkasberg)"
|
||||
short_description: Perform switch restart on devices running Lenovo CNOS
|
||||
description:
|
||||
- This module allows you to restart the switch using the current startup configuration.
|
||||
The module is usually invoked after the running configuration has been saved over the startup configuration.
|
||||
This module uses SSH to manage network device configuration.
|
||||
The results of the operation can be viewed in results directory.
|
||||
For more information about this module from Lenovo and customizing it usage for your
|
||||
use cases, please visit U(http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_reload.html)
|
||||
version_added: "2.3"
|
||||
extends_documentation_fragment: cnos
|
||||
options: {}
|
||||
|
||||
'''
|
||||
EXAMPLES = '''
|
||||
Tasks : The following are examples of using the module cnos_reload. These are written in the main.yml file of the tasks directory.
|
||||
---
|
||||
- name: Test Reload
|
||||
cnos_reload:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_reload_{{ inventory_hostname }}_output.txt"
|
||||
'''
|
||||
RETURN = '''
|
||||
msg:
|
||||
description: Success or failure message
|
||||
returned: always
|
||||
type: string
|
||||
sample: "Device is Reloading. Please wait..."
|
||||
'''
|
||||
|
||||
import sys
|
||||
try:
|
||||
import paramiko
|
||||
HAS_PARAMIKO = True
|
||||
except ImportError:
|
||||
HAS_PARAMIKO = False
|
||||
import time
|
||||
import socket
|
||||
import array
|
||||
import json
|
||||
import time
|
||||
import re
|
||||
try:
|
||||
from ansible.module_utils import cnos
|
||||
HAS_LIB = True
|
||||
except:
|
||||
HAS_LIB = False
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
outputfile=dict(required=True),
|
||||
host=dict(required=True),
|
||||
username=dict(required=True),
|
||||
password=dict(required=True, no_log=True),
|
||||
enablePassword=dict(required=False, no_log=True),
|
||||
deviceType=dict(required=True),),
|
||||
supports_check_mode=False)
|
||||
|
||||
username = module.params['username']
|
||||
password = module.params['password']
|
||||
enablePassword = module.params['enablePassword']
|
||||
cliCommand = "reload \n"
|
||||
outputfile = module.params['outputfile']
|
||||
hostIP = module.params['host']
|
||||
deviceType = module.params['deviceType']
|
||||
output = ""
|
||||
if not HAS_PARAMIKO:
|
||||
module.fail_json(msg='paramiko is required for this module')
|
||||
|
||||
# Create instance of SSHClient object
|
||||
remote_conn_pre = paramiko.SSHClient()
|
||||
|
||||
# Automatically add untrusted hosts (make sure okay for security policy in your environment)
|
||||
remote_conn_pre.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
|
||||
# initiate SSH connection with the switch
|
||||
remote_conn_pre.connect(hostIP, username=username, password=password)
|
||||
time.sleep(2)
|
||||
|
||||
# Use invoke_shell to establish an 'interactive session'
|
||||
remote_conn = remote_conn_pre.invoke_shell()
|
||||
time.sleep(2)
|
||||
|
||||
# Enable and enter configure terminal then send command
|
||||
output = output + cnos.waitForDeviceResponse("\n", ">", 2, remote_conn)
|
||||
|
||||
output = output + cnos.enterEnableModeForDevice(enablePassword, 3, remote_conn)
|
||||
|
||||
# Make terminal length = 0
|
||||
output = output + cnos.waitForDeviceResponse("terminal length 0\n", "#", 2, remote_conn)
|
||||
|
||||
# Send the CLi command
|
||||
output = output + cnos.waitForDeviceResponse(cliCommand, "(y/n):", 2, remote_conn)
|
||||
|
||||
# Send the Confirmation y
|
||||
output = output + cnos.waitForDeviceResponse("y\n", "#", 2, remote_conn)
|
||||
|
||||
# Save it into the file
|
||||
file = open(outputfile, "a")
|
||||
file.write(output)
|
||||
file.close()
|
||||
|
||||
errorMsg = cnos.checkOutputForError(output)
|
||||
if(errorMsg in "Device Response Timed out"):
|
||||
module.exit_json(changed=True, msg="Device is Reloading. Please wait...")
|
||||
else:
|
||||
module.fail_json(msg=errorMsg)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
276
lib/ansible/modules/network/cnos/cnos_rollback.py
Normal file
276
lib/ansible/modules/network/cnos/cnos_rollback.py
Normal file
@@ -0,0 +1,276 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
#
|
||||
# Copyright (C) 2017 Lenovo, 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/>.
|
||||
#
|
||||
# Module to Rollback Config back to Lenovo Switches
|
||||
#
|
||||
# Lenovo Networking
|
||||
#
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: cnos_rollback
|
||||
author: "Dave Kasberg (@dkasberg)"
|
||||
short_description: Roll back the running or startup configuration from a remote server on devices running Lenovo CNOS
|
||||
description:
|
||||
- This module allows you to work with switch configurations. It provides a way to roll back configurations
|
||||
of a switch from a remote server. This is achieved by using startup or running configurations of the target
|
||||
device that were previously backed up to a remote server using FTP, SFTP, TFTP, or SCP.
|
||||
The first step is to create a directory from where the remote server can be reached. The next step is to
|
||||
provide the full file path of the backup configuration's location. Authentication details required by the
|
||||
remote server must be provided as well.
|
||||
By default, this method overwrites the switch's configuration file with the newly downloaded file.
|
||||
This module uses SSH to manage network device configuration.
|
||||
The results of the operation will be placed in a directory named 'results'
|
||||
that must be created by the user in their local directory to where the playbook is run.
|
||||
For more information about this module from Lenovo and customizing it usage for your
|
||||
use cases, please visit U(http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_rollback.html)
|
||||
version_added: "2.3"
|
||||
extends_documentation_fragment: cnos
|
||||
options:
|
||||
configType:
|
||||
description:
|
||||
- This refers to the type of configuration which will be used for the rolling back process.
|
||||
The choices are the running or startup configurations. There is no default value, so it will result
|
||||
in an error if the input is incorrect.
|
||||
required: Yes
|
||||
default: Null
|
||||
choices: [running-config, startup-config]
|
||||
protocol:
|
||||
description:
|
||||
- This refers to the protocol used by the network device to interact with the remote server from where to
|
||||
download the backup configuration. The choices are FTP, SFTP, TFTP, or SCP. Any other protocols will result
|
||||
in error. If this parameter is not specified, there is no default value to be used.
|
||||
required: Yes
|
||||
default: Null
|
||||
choices: [SFTP, SCP, FTP, TFTP]
|
||||
rcserverip:
|
||||
description:
|
||||
- This specifies the IP Address of the remote server from where the backup configuration will be downloaded.
|
||||
required: Yes
|
||||
default: Null
|
||||
rcpath:
|
||||
description:
|
||||
- This specifies the full file path of the configuration file located on the remote server. In case the relative
|
||||
path is used as the variable value, the root folder for the user of the server needs to be specified.
|
||||
required: Yes
|
||||
default: Null
|
||||
serverusername:
|
||||
description:
|
||||
- Specify the username for the server relating to the protocol used.
|
||||
required: Yes
|
||||
default: Null
|
||||
serverpassword:
|
||||
description:
|
||||
- Specify the password for the server relating to the protocol used.
|
||||
required: Yes
|
||||
default: Null
|
||||
'''
|
||||
EXAMPLES = '''
|
||||
Tasks : The following are examples of using the module cnos_rollback. These are written in the main.yml file of the tasks directory.
|
||||
---
|
||||
|
||||
- name: Test Rollback of config - Running config
|
||||
cnos_rolback:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_rollback_{{ inventory_hostname }}_output.txt"
|
||||
configType: running-config
|
||||
protocol: "sftp"
|
||||
serverip: "10.241.106.118"
|
||||
rcpath: "/root/cnos/G8272-running-config.txt"
|
||||
serverusername: "root"
|
||||
serverpassword: "root123"
|
||||
|
||||
- name: Test Rollback of config - Startup config
|
||||
cnos_rolback:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_rollback_{{ inventory_hostname }}_output.txt"
|
||||
configType: startup-config
|
||||
protocol: "sftp"
|
||||
serverip: "10.241.106.118"
|
||||
rcpath: "/root/cnos/G8272-startup-config.txt"
|
||||
serverusername: "root"
|
||||
serverpassword: "root123"
|
||||
|
||||
- name: Test Rollback of config - Running config - TFTP
|
||||
cnos_rolback:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_rollback_{{ inventory_hostname }}_output.txt"
|
||||
configType: running-config
|
||||
protocol: "tftp"
|
||||
serverip: "10.241.106.118"
|
||||
rcpath: "/anil/G8272-running-config.txt"
|
||||
serverusername: "root"
|
||||
serverpassword: "root123"
|
||||
|
||||
- name: Test Rollback of config - Startup config - TFTP
|
||||
cnos_rolback:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_rollback_{{ inventory_hostname }}_output.txt"
|
||||
configType: startup-config
|
||||
protocol: "tftp"
|
||||
serverip: "10.241.106.118"
|
||||
rcpath: "/anil/G8272-startup-config.txt"
|
||||
serverusername: "root"
|
||||
serverpassword: "root123"
|
||||
|
||||
'''
|
||||
RETURN = '''
|
||||
msg:
|
||||
description: Success or failure message
|
||||
returned: always
|
||||
type: string
|
||||
sample: "Config file tranferred to Device"
|
||||
'''
|
||||
|
||||
import sys
|
||||
try:
|
||||
import paramiko
|
||||
HAS_PARAMIKO = True
|
||||
except ImportError:
|
||||
HAS_PARAMIKO = False
|
||||
import time
|
||||
import socket
|
||||
import array
|
||||
import json
|
||||
import time
|
||||
import re
|
||||
try:
|
||||
from ansible.module_utils import cnos
|
||||
HAS_LIB = True
|
||||
except:
|
||||
HAS_LIB = False
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
outputfile=dict(required=True),
|
||||
host=dict(required=True),
|
||||
username=dict(required=True),
|
||||
password=dict(required=True, no_log=True),
|
||||
enablePassword=dict(required=False, no_log=True),
|
||||
deviceType=dict(required=True),
|
||||
configType=dict(required=True),
|
||||
protocol=dict(required=True),
|
||||
serverip=dict(required=True),
|
||||
rcpath=dict(required=True),
|
||||
serverusername=dict(required=False),
|
||||
serverpassword=dict(required=False, no_log=True),),
|
||||
supports_check_mode=False)
|
||||
|
||||
username = module.params['username']
|
||||
password = module.params['password']
|
||||
enablePassword = module.params['enablePassword']
|
||||
outputfile = module.params['outputfile']
|
||||
host = module.params['host']
|
||||
deviceType = module.params['deviceType']
|
||||
configType = module.params['configType']
|
||||
protocol = module.params['protocol'].lower()
|
||||
rcserverip = module.params['serverip']
|
||||
rcpath = module.params['rcpath']
|
||||
serveruser = module.params['serverusername']
|
||||
serverpwd = module.params['serverpassword']
|
||||
output = ""
|
||||
timeout = 90
|
||||
tftptimeout = 450
|
||||
if not HAS_PARAMIKO:
|
||||
module.fail_json(msg='paramiko is required for this module')
|
||||
|
||||
# Create instance of SSHClient object
|
||||
remote_conn_pre = paramiko.SSHClient()
|
||||
|
||||
# Automatically add untrusted hosts (make sure okay for security policy in your environment)
|
||||
remote_conn_pre.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
|
||||
# initiate SSH connection with the switch
|
||||
remote_conn_pre.connect(host, username=username, password=password)
|
||||
time.sleep(2)
|
||||
|
||||
# Use invoke_shell to establish an 'interactive session'
|
||||
remote_conn = remote_conn_pre.invoke_shell()
|
||||
time.sleep(2)
|
||||
|
||||
# Enable and enter configure terminal then send command
|
||||
output = output + cnos.waitForDeviceResponse("\n", ">", 2, remote_conn)
|
||||
|
||||
output = output + cnos.enterEnableModeForDevice(enablePassword, 3, remote_conn)
|
||||
|
||||
# Make terminal length = 0
|
||||
output = output + cnos.waitForDeviceResponse("terminal length 0\n", "#", 2, remote_conn)
|
||||
|
||||
# Invoke method for Config transfer from server
|
||||
if(configType == 'running-config'):
|
||||
if(protocol == "tftp" or protocol == "ftp"):
|
||||
transfer_status = cnos.doRunningConfigRollback(protocol, tftptimeout, rcserverip, rcpath, serveruser, serverpwd, remote_conn)
|
||||
elif(protocol == "sftp" or protocol == "scp"):
|
||||
transfer_status = cnos.doSecureRunningConfigRollback(protocol, timeout, rcserverip, rcpath, serveruser, serverpwd, remote_conn)
|
||||
else:
|
||||
transfer_status = "Invalid Protocol option"
|
||||
elif(configType == 'startup-config'):
|
||||
if(protocol == "tftp" or protocol == "ftp"):
|
||||
transfer_status = cnos.doStartUpConfigRollback(protocol, tftptimeout, rcserverip, rcpath, serveruser, serverpwd, remote_conn)
|
||||
elif(protocol == "sftp" or protocol == "scp"):
|
||||
transfer_status = cnos.doSecureStartUpConfigRollback(protocol, timeout, rcserverip, rcpath, serveruser, serverpwd, remote_conn)
|
||||
else:
|
||||
transfer_status = "Invalid Protocol option"
|
||||
else:
|
||||
transfer_status = "Invalid configType Option"
|
||||
|
||||
output = output + "\n Config Transfer status \n" + transfer_status
|
||||
|
||||
# Save it into the file
|
||||
file = open(outputfile, "a")
|
||||
file.write(output)
|
||||
file.close()
|
||||
|
||||
# need to add logic to check when changes occur or not
|
||||
errorMsg = cnos.checkOutputForError(output)
|
||||
if(errorMsg is None):
|
||||
module.exit_json(changed=True, msg="Config file tranferred to Device")
|
||||
else:
|
||||
module.fail_json(msg=errorMsg)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
151
lib/ansible/modules/network/cnos/cnos_save.py
Normal file
151
lib/ansible/modules/network/cnos/cnos_save.py
Normal file
@@ -0,0 +1,151 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
#
|
||||
# Copyright (C) 2017 Lenovo, 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/>.
|
||||
#
|
||||
# Module to save running config to start up config to Lenovo Switches
|
||||
# Lenovo Networking
|
||||
#
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: cnos_save
|
||||
author: "Dave Kasberg (@dkasberg)"
|
||||
short_description: Save the running configuration as the startup configuration on devices running Lenovo CNOS
|
||||
description:
|
||||
- This module allows you to copy the running configuration of a switch over its startup configuration.
|
||||
It is recommended to use this module shortly after any major configuration changes so they persist after
|
||||
a switch restart. This module uses SSH to manage network device configuration.
|
||||
The results of the operation will be placed in a directory named 'results'
|
||||
that must be created by the user in their local directory to where the playbook is run.
|
||||
For more information about this module from Lenovo and customizing it usage for your
|
||||
use cases, please visit U(http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_save.html)
|
||||
version_added: "2.3"
|
||||
extends_documentation_fragment: cnos
|
||||
options: {}
|
||||
|
||||
'''
|
||||
EXAMPLES = '''
|
||||
Tasks : The following are examples of using the module cnos_save. These are written in the main.yml file of the tasks directory.
|
||||
---
|
||||
- name: Test Save
|
||||
cnos_save:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_save_{{ inventory_hostname }}_output.txt"
|
||||
'''
|
||||
RETURN = '''
|
||||
msg:
|
||||
description: Success or failure message
|
||||
returned: always
|
||||
type: string
|
||||
sample: "Switch Running Config is Saved to Startup Config"
|
||||
'''
|
||||
|
||||
import sys
|
||||
try:
|
||||
import paramiko
|
||||
HAS_PARAMIKO = True
|
||||
except ImportError:
|
||||
HAS_PARAMIKO = False
|
||||
import time
|
||||
import socket
|
||||
import array
|
||||
import json
|
||||
import time
|
||||
import re
|
||||
try:
|
||||
from ansible.module_utils import cnos
|
||||
HAS_LIB = True
|
||||
except:
|
||||
HAS_LIB = False
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
outputfile=dict(required=True),
|
||||
host=dict(required=True),
|
||||
username=dict(required=True),
|
||||
password=dict(required=True, no_log=True),
|
||||
enablePassword=dict(required=False, no_log=True),
|
||||
deviceType=dict(required=True),),
|
||||
supports_check_mode=False)
|
||||
|
||||
username = module.params['username']
|
||||
password = module.params['password']
|
||||
enablePassword = module.params['enablePassword']
|
||||
cliCommand = "save memory \n"
|
||||
outputfile = module.params['outputfile']
|
||||
hostIP = module.params['host']
|
||||
deviceType = module.params['deviceType']
|
||||
output = ""
|
||||
if not HAS_PARAMIKO:
|
||||
module.fail_json(msg='paramiko is required for this module')
|
||||
|
||||
# Create instance of SSHClient object
|
||||
remote_conn_pre = paramiko.SSHClient()
|
||||
|
||||
# Automatically add untrusted hosts (make sure okay for security policy in your environment)
|
||||
remote_conn_pre.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
|
||||
# initiate SSH connection with the switch
|
||||
remote_conn_pre.connect(hostIP, username=username, password=password)
|
||||
time.sleep(2)
|
||||
|
||||
# Use invoke_shell to establish an 'interactive session'
|
||||
remote_conn = remote_conn_pre.invoke_shell()
|
||||
time.sleep(2)
|
||||
|
||||
# Enable and enter configure terminal then send command
|
||||
output = output + cnos.waitForDeviceResponse("\n", ">", 2, remote_conn)
|
||||
|
||||
output = output + cnos.enterEnableModeForDevice(enablePassword, 3, remote_conn)
|
||||
|
||||
# Make terminal length = 0
|
||||
output = output + cnos.waitForDeviceResponse("terminal length 0\n", "#", 2, remote_conn)
|
||||
|
||||
# cnos.debugOutput(cliCommand)
|
||||
# Send the CLi command
|
||||
output = output + cnos.waitForDeviceResponse(cliCommand, "#", 2, remote_conn)
|
||||
|
||||
# Save it into the file
|
||||
file = open(outputfile, "a")
|
||||
file.write(output)
|
||||
file.close()
|
||||
|
||||
errorMsg = cnos.checkOutputForError(output)
|
||||
if(errorMsg is None):
|
||||
module.exit_json(changed=True, msg="Switch Running Config is Saved to Startup Config ")
|
||||
else:
|
||||
module.fail_json(msg=errorMsg)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
149
lib/ansible/modules/network/cnos/cnos_showrun.py
Normal file
149
lib/ansible/modules/network/cnos/cnos_showrun.py
Normal file
@@ -0,0 +1,149 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
#
|
||||
# Copyright (C) 2017 Lenovo, 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/>.
|
||||
#
|
||||
# Module to display running config of Switches
|
||||
# Lenovo Networking
|
||||
#
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: cnos_showrun
|
||||
author: "Dave Kasberg (@dkasberg)"
|
||||
short_description: Collect the current running configuration on devices running Lenovo CNOS
|
||||
description:
|
||||
- This module allows you to view the switch running configuration. It executes the display running-config CLI
|
||||
command on a switch and returns a file containing the current running configuration of the target network
|
||||
device. This module uses SSH to manage network device configuration.
|
||||
The results of the operation will be placed in a directory named 'results'
|
||||
that must be created by the user in their local directory to where the playbook is run.
|
||||
For more information about this module from Lenovo and customizing it usage for your
|
||||
use cases, please visit U(http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_showrun.html)
|
||||
version_added: "2.3"
|
||||
extends_documentation_fragment: cnos
|
||||
options: {}
|
||||
|
||||
'''
|
||||
EXAMPLES = '''
|
||||
Tasks : The following are examples of using the module cnos_showrun. These are written in the main.yml file of the tasks directory.
|
||||
---
|
||||
- name: Run show running-config
|
||||
cnos_showrun:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_showrun_{{ inventory_hostname }}_output.txt"
|
||||
|
||||
'''
|
||||
RETURN = '''
|
||||
msg:
|
||||
description: Success or failure message
|
||||
returned: always
|
||||
type: string
|
||||
sample: "Running Configuration saved in file"
|
||||
'''
|
||||
|
||||
import sys
|
||||
try:
|
||||
import paramiko
|
||||
HAS_PARAMIKO = True
|
||||
except ImportError:
|
||||
HAS_PARAMIKO = False
|
||||
import time
|
||||
import socket
|
||||
import array
|
||||
import json
|
||||
import time
|
||||
import re
|
||||
try:
|
||||
from ansible.module_utils import cnos
|
||||
HAS_LIB = True
|
||||
except:
|
||||
HAS_LIB = False
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
outputfile=dict(required=True),
|
||||
host=dict(required=True),
|
||||
username=dict(required=True),
|
||||
password=dict(required=True, no_log=True),
|
||||
enablePassword=dict(required=False, no_log=True),),
|
||||
supports_check_mode=False)
|
||||
|
||||
username = module.params['username']
|
||||
password = module.params['password']
|
||||
enablePassword = module.params['enablePassword']
|
||||
cliCommand = "display running-config"
|
||||
outputfile = module.params['outputfile']
|
||||
hostIP = module.params['host']
|
||||
output = ""
|
||||
if not HAS_PARAMIKO:
|
||||
module.fail_json(msg='paramiko is required for this module')
|
||||
|
||||
# Create instance of SSHClient object
|
||||
remote_conn_pre = paramiko.SSHClient()
|
||||
|
||||
# Automatically add untrusted hosts (make sure okay for security policy in your environment)
|
||||
remote_conn_pre.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
|
||||
# initiate SSH connection with the switch
|
||||
remote_conn_pre.connect(hostIP, username=username, password=password)
|
||||
time.sleep(2)
|
||||
|
||||
# Use invoke_shell to establish an 'interactive session'
|
||||
remote_conn = remote_conn_pre.invoke_shell()
|
||||
time.sleep(2)
|
||||
|
||||
# Enable and enter configure terminal then send command
|
||||
output = output + cnos.waitForDeviceResponse("\n", ">", 2, remote_conn)
|
||||
|
||||
output = output + cnos.enterEnableModeForDevice(enablePassword, 3, remote_conn)
|
||||
|
||||
# Make terminal length = 0
|
||||
output = output + cnos.waitForDeviceResponse("terminal length 0\n", "#", 2, remote_conn)
|
||||
|
||||
# Send the CLi command
|
||||
output = output + cnos.waitForDeviceResponse(cliCommand + "\n", "#", 2, remote_conn)
|
||||
|
||||
# Save it into the file
|
||||
file = open(outputfile, "a")
|
||||
file.write(output)
|
||||
file.close()
|
||||
|
||||
errorMsg = cnos.checkOutputForError(output)
|
||||
if(errorMsg is None):
|
||||
module.exit_json(changed=True, msg="Running Configuration saved in file ")
|
||||
else:
|
||||
module.fail_json(msg=errorMsg)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
190
lib/ansible/modules/network/cnos/cnos_template.py
Normal file
190
lib/ansible/modules/network/cnos/cnos_template.py
Normal file
@@ -0,0 +1,190 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
#
|
||||
# Copyright (C) 2017 Lenovo, 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/>.
|
||||
#
|
||||
# Module to send CLI templates to Lenovo Switches
|
||||
# Lenovo Networking
|
||||
#
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: cnos_template
|
||||
author: "Dave Kasberg (@dkasberg)"
|
||||
short_description: Manage switch configuration using templates on devices running Lenovo CNOS
|
||||
description:
|
||||
- This module allows you to work with the running configuration of a switch. It provides a way
|
||||
to execute a set of CNOS commands on a switch by evaluating the current running configuration
|
||||
and executing the commands only if the specific settings have not been already configured.
|
||||
The configuration source can be a set of commands or a template written in the Jinja2 templating language.
|
||||
This module uses SSH to manage network device configuration.
|
||||
The results of the operation will be placed in a directory named 'results'
|
||||
that must be created by the user in their local directory to where the playbook is run.
|
||||
For more information about this module from Lenovo and customizing it usage for your
|
||||
use cases, please visit U(http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_template.html)
|
||||
version_added: "2.3"
|
||||
extends_documentation_fragment: cnos
|
||||
options:
|
||||
commandfile:
|
||||
description:
|
||||
- This specifies the path to the CNOS command file which needs to be applied. This usually
|
||||
comes from the commands folder. Generally this file is the output of the variables applied
|
||||
on a template file. So this command is preceded by a template module.
|
||||
Note The command file must contain the Ansible keyword {{ inventory_hostname }} in its
|
||||
filename to ensure that the command file is unique for each switch and condition.
|
||||
If this is omitted, the command file will be overwritten during iteration. For example,
|
||||
commandfile=./commands/clos_leaf_bgp_{{ inventory_hostname }}_commands.txt
|
||||
required: true
|
||||
default: Null
|
||||
'''
|
||||
EXAMPLES = '''
|
||||
Tasks : The following are examples of using the module cnos_template. These are written in the main.yml file of the tasks directory.
|
||||
---
|
||||
- name: Replace Config CLI command template with values
|
||||
template:
|
||||
src: demo_template.j2
|
||||
dest: "./commands/demo_template_{{ inventory_hostname }}_commands.txt"
|
||||
vlanid1: 13
|
||||
slot_chassis_number1: "1/2"
|
||||
portchannel_interface_number1: 100
|
||||
portchannel_mode1: "active"
|
||||
|
||||
- name: Applying CLI commands on Switches
|
||||
cnos_template:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
commandfile: "./commands/demo_template_{{ inventory_hostname }}_commands.txt"
|
||||
outputfile: "./results/demo_template_command_{{ inventory_hostname }}_output.txt"
|
||||
|
||||
'''
|
||||
RETURN = '''
|
||||
msg:
|
||||
description: Success or failure message
|
||||
returned: always
|
||||
type: string
|
||||
sample: "Template Applied."
|
||||
'''
|
||||
|
||||
import sys
|
||||
try:
|
||||
import paramiko
|
||||
HAS_PARAMIKO = True
|
||||
except ImportError:
|
||||
HAS_PARAMIKO = False
|
||||
import time
|
||||
import socket
|
||||
import array
|
||||
import json
|
||||
import time
|
||||
import re
|
||||
try:
|
||||
from ansible.module_utils import cnos
|
||||
HAS_LIB = True
|
||||
except:
|
||||
HAS_LIB = False
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
commandfile=dict(required=True),
|
||||
outputfile=dict(required=True),
|
||||
host=dict(required=True),
|
||||
deviceType=dict(required=True),
|
||||
username=dict(required=True),
|
||||
password=dict(required=True, no_log=True),
|
||||
enablePassword=dict(required=False, no_log=True),),
|
||||
supports_check_mode=False)
|
||||
username = module.params['username']
|
||||
password = module.params['password']
|
||||
enablePassword = module.params['enablePassword']
|
||||
commandfile = module.params['commandfile']
|
||||
outputfile = module.params['outputfile']
|
||||
deviceType = module.params['deviceType']
|
||||
hostIP = module.params['host']
|
||||
output = ""
|
||||
if not HAS_PARAMIKO:
|
||||
module.fail_json(msg='paramiko is required for this module')
|
||||
|
||||
# Create instance of SSHClient object
|
||||
remote_conn_pre = paramiko.SSHClient()
|
||||
|
||||
# Automatically add untrusted hosts (make sure okay for security policy in your environment)
|
||||
remote_conn_pre.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
|
||||
# initiate SSH connection with the switch
|
||||
remote_conn_pre.connect(hostIP, username=username, password=password)
|
||||
time.sleep(2)
|
||||
|
||||
# Use invoke_shell to establish an 'interactive session'
|
||||
remote_conn = remote_conn_pre.invoke_shell()
|
||||
time.sleep(2)
|
||||
|
||||
# Enable and enter configure terminal then send command
|
||||
output = output + cnos.waitForDeviceResponse("\n", ">", 2, remote_conn)
|
||||
|
||||
output = output + cnos.enterEnableModeForDevice(enablePassword, 3, remote_conn)
|
||||
|
||||
# Make terminal length = 0
|
||||
output = output + cnos.waitForDeviceResponse("terminal length 0\n", "#", 2, remote_conn)
|
||||
|
||||
# Go to config mode
|
||||
output = output + cnos.waitForDeviceResponse("configure d\n", "(config)#", 2, remote_conn)
|
||||
|
||||
# Send commands one by one to the device
|
||||
# with open(commandfile, "r") as f:
|
||||
f = open(commandfile, "r")
|
||||
for line in f:
|
||||
# Omit the comment lines in template file
|
||||
if not line.startswith("#"):
|
||||
command = line
|
||||
if not line.endswith("\n"):
|
||||
command = command + "\n"
|
||||
response = cnos.waitForDeviceResponse(command, "#", 2, remote_conn)
|
||||
errorMsg = cnos.checkOutputForError(response)
|
||||
output = output + response
|
||||
if(errorMsg is not None):
|
||||
break # To cater to Mufti case
|
||||
# Write to memory
|
||||
output = output + cnos.waitForDeviceResponse("save\n", "#", 3, remote_conn)
|
||||
# Write output to file
|
||||
file = open(outputfile, "a")
|
||||
file.write(output)
|
||||
file.close()
|
||||
|
||||
# Logic to check when changes occur or not
|
||||
errorMsg = cnos.checkOutputForError(output)
|
||||
if(errorMsg is None):
|
||||
module.exit_json(changed=True, msg="Template Applied")
|
||||
else:
|
||||
module.fail_json(msg=errorMsg)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
357
lib/ansible/modules/network/cnos/cnos_vlag.py
Normal file
357
lib/ansible/modules/network/cnos/cnos_vlag.py
Normal file
@@ -0,0 +1,357 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
#
|
||||
# Copyright (C) 2017 Lenovo, 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/>.
|
||||
#
|
||||
# Module to send VLAG commands to Lenovo Switches
|
||||
# Lenovo Networking
|
||||
#
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: cnos_vlag
|
||||
author: "Dave Kasberg (@dkasberg)"
|
||||
short_description: Manage VLAG resources and attributes on devices running Lenovo CNOS
|
||||
description:
|
||||
- This module allows you to work with virtual Link Aggregation Groups
|
||||
(vLAG) related configurations. The operators used are overloaded to ensure
|
||||
control over switch vLAG configurations. Apart from the regular device
|
||||
connection related attributes, there are four vLAG arguments which are
|
||||
overloaded variables that will perform further configurations. They are
|
||||
vlagArg1, vlagArg2, vlagArg3, and vlagArg4. For more details on how to use
|
||||
these arguments, see [Overloaded Variables].
|
||||
This module uses SSH to manage network device configuration.
|
||||
The results of the operation will be placed in a directory named 'results'
|
||||
that must be created by the user in their local directory to where the playbook is run.
|
||||
For more information about this module from Lenovo and customizing it usage for your
|
||||
use cases, please visit U(http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_vlag.html)
|
||||
version_added: "2.3"
|
||||
extends_documentation_fragment: cnos
|
||||
options:
|
||||
vlagArg1:
|
||||
description:
|
||||
- This is an overloaded vlag first argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: Yes
|
||||
default: Null
|
||||
choices: [enable, auto-recovery,config-consistency,isl,mac-address-table,peer-gateway,priority,startup-delay,tier-id,vrrp,instance,hlthchk]
|
||||
vlagArg2:
|
||||
description:
|
||||
- This is an overloaded vlag second argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: No
|
||||
default: Null
|
||||
choices: [Interval in seconds,disable or strict,Port Aggregation Number,VLAG priority,Delay time in seconds,VLAG tier-id value,
|
||||
VLAG instance number,keepalive-attempts,keepalive-interval,retry-interval,peer-ip]
|
||||
vlagArg3:
|
||||
description:
|
||||
- This is an overloaded vlag third argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: No
|
||||
default: Null
|
||||
choices: [enable or port-aggregation,Number of keepalive attempts,Interval in seconds,Interval in seconds,VLAG health check peer IP4 address]
|
||||
vlagArg4:
|
||||
description:
|
||||
- This is an overloaded vlag fourth argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: No
|
||||
default: Null
|
||||
choices: [Port Aggregation Number,default or management]
|
||||
|
||||
'''
|
||||
EXAMPLES = '''
|
||||
|
||||
Tasks : The following are examples of using the module cnos_vlag. These are written in the main.yml file of the tasks directory.
|
||||
---
|
||||
- name: Test Vlag - enable
|
||||
cnos_vlag:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username']}}"
|
||||
password: "{{ hostvars[inventory_hostname]['password']}}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
|
||||
outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
|
||||
vlagArg1: "enable"
|
||||
|
||||
- name: Test Vlag - autorecovery
|
||||
cnos_vlag:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username']}}"
|
||||
password: "{{ hostvars[inventory_hostname]['password']}}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
|
||||
outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
|
||||
vlagArg1: "auto-recovery"
|
||||
vlagArg2: 266
|
||||
|
||||
- name: Test Vlag - config-consistency
|
||||
cnos_vlag:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username']}}"
|
||||
password: "{{ hostvars[inventory_hostname]['password']}}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
|
||||
outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
|
||||
vlagArg1: "config-consistency"
|
||||
vlagArg2: "strict"
|
||||
|
||||
- name: Test Vlag - isl
|
||||
cnos_vlag:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username']}}"
|
||||
password: "{{ hostvars[inventory_hostname]['password']}}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
|
||||
outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
|
||||
vlagArg1: "isl"
|
||||
vlagArg2: 23
|
||||
|
||||
- name: Test Vlag - mac-address-table
|
||||
cnos_vlag:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username']}}"
|
||||
password: "{{ hostvars[inventory_hostname]['password']}}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
|
||||
outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
|
||||
vlagArg1: "mac-address-table"
|
||||
|
||||
- name: Test Vlag - peer-gateway
|
||||
cnos_vlag:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username']}}"
|
||||
password: "{{ hostvars[inventory_hostname]['password']}}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
|
||||
outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
|
||||
vlagArg1: "peer-gateway"
|
||||
|
||||
- name: Test Vlag - priority
|
||||
cnos_vlag:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username']}}"
|
||||
password: "{{ hostvars[inventory_hostname]['password']}}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
|
||||
outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
|
||||
vlagArg1: "priority"
|
||||
vlagArg2: 1313
|
||||
|
||||
- name: Test Vlag - startup-delay
|
||||
cnos_vlag:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username']}}"
|
||||
password: "{{ hostvars[inventory_hostname]['password']}}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
|
||||
outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
|
||||
vlagArg1: "startup-delay"
|
||||
vlagArg2: 323
|
||||
|
||||
- name: Test Vlag - tier-id
|
||||
cnos_vlag:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username']}}"
|
||||
password: "{{ hostvars[inventory_hostname]['password']}}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
|
||||
outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
|
||||
vlagArg1: "tier-id"
|
||||
vlagArg2: 313
|
||||
|
||||
- name: Test Vlag - vrrp
|
||||
cnos_vlag:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username']}}"
|
||||
password: "{{ hostvars[inventory_hostname]['password']}}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
|
||||
outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
|
||||
vlagArg1: "vrrp"
|
||||
|
||||
- name: Test Vlag - instance
|
||||
cnos_vlag:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username']}}"
|
||||
password: "{{ hostvars[inventory_hostname]['password']}}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
|
||||
outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
|
||||
vlagArg1: "instance"
|
||||
vlagArg2: 33
|
||||
vlagArg3: 333
|
||||
|
||||
- name: Test Vlag - instance2
|
||||
cnos_vlag:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username']}}"
|
||||
password: "{{ hostvars[inventory_hostname]['password']}}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
|
||||
outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
|
||||
vlagArg1: "instance"
|
||||
vlagArg2: "33"
|
||||
|
||||
- name: Test Vlag - keepalive-attempts
|
||||
cnos_vlag:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username']}}"
|
||||
password: "{{ hostvars[inventory_hostname]['password']}}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
|
||||
outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
|
||||
vlagArg1: "hlthchk"
|
||||
vlagArg2: "keepalive-attempts"
|
||||
vlagArg3: 13
|
||||
|
||||
- name: Test Vlag - keepalive-interval
|
||||
cnos_vlag:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username']}}"
|
||||
password: "{{ hostvars[inventory_hostname]['password']}}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
|
||||
outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
|
||||
vlagArg1: "hlthchk"
|
||||
vlagArg2: "keepalive-interval"
|
||||
vlagArg3: 131
|
||||
|
||||
- name: Test Vlag - retry-interval
|
||||
cnos_vlag:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username']}}"
|
||||
password: "{{ hostvars[inventory_hostname]['password']}}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
|
||||
outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
|
||||
vlagArg1: "hlthchk"
|
||||
vlagArg2: "retry-interval"
|
||||
vlagArg3: 133
|
||||
|
||||
- name: Test Vlag - peer ip
|
||||
cnos_vlag:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username']}}"
|
||||
password: "{{ hostvars[inventory_hostname]['password']}}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType']}}"
|
||||
outputfile: "./results/cnos_vlag_{{ inventory_hostname }}_output.txt"
|
||||
vlagArg1: "hlthchk"
|
||||
vlagArg2: "peer-ip"
|
||||
vlagArg3: "1.2.3.4"
|
||||
|
||||
'''
|
||||
RETURN = '''
|
||||
msg:
|
||||
description: Success or failure message
|
||||
returned: always
|
||||
type: string
|
||||
sample: "vLAG configurations accomplished"
|
||||
'''
|
||||
|
||||
import sys
|
||||
try:
|
||||
import paramiko
|
||||
HAS_PARAMIKO = True
|
||||
except ImportError:
|
||||
HAS_PARAMIKO = False
|
||||
import time
|
||||
import socket
|
||||
import array
|
||||
import json
|
||||
import time
|
||||
import re
|
||||
try:
|
||||
from ansible.module_utils import cnos
|
||||
HAS_LIB = True
|
||||
except:
|
||||
HAS_LIB = False
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
def main():
|
||||
#
|
||||
# Define parameters for vlag creation entry
|
||||
#
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
outputfile=dict(required=True),
|
||||
host=dict(required=True),
|
||||
username=dict(required=True),
|
||||
password=dict(required=True, no_log=True),
|
||||
enablePassword=dict(required=False, no_log=True),
|
||||
deviceType=dict(required=True),
|
||||
vlagArg1=dict(required=True),
|
||||
vlagArg2=dict(required=False),
|
||||
vlagArg3=dict(required=False),
|
||||
vlagArg4=dict(required=False),),
|
||||
supports_check_mode=False)
|
||||
|
||||
username = module.params['username']
|
||||
password = module.params['password']
|
||||
enablePassword = module.params['enablePassword']
|
||||
outputfile = module.params['outputfile']
|
||||
hostIP = module.params['host']
|
||||
deviceType = module.params['deviceType']
|
||||
vlagArg1 = module.params['vlagArg1']
|
||||
vlagArg2 = module.params['vlagArg2']
|
||||
vlagArg3 = module.params['vlagArg3']
|
||||
vlagArg4 = module.params['vlagArg4']
|
||||
output = ""
|
||||
if not HAS_PARAMIKO:
|
||||
module.fail_json(msg='paramiko is required for this module')
|
||||
|
||||
# Create instance of SSHClient object
|
||||
remote_conn_pre = paramiko.SSHClient()
|
||||
|
||||
# Automatically add untrusted hosts (make sure okay for security policy in
|
||||
# your environment)
|
||||
remote_conn_pre.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
|
||||
# initiate SSH connection with the switch
|
||||
remote_conn_pre.connect(hostIP, username=username, password=password)
|
||||
time.sleep(2)
|
||||
|
||||
# Use invoke_shell to establish an 'interactive session'
|
||||
remote_conn = remote_conn_pre.invoke_shell()
|
||||
time.sleep(2)
|
||||
|
||||
# Enable and enter configure terminal then send command
|
||||
output = output + cnos.waitForDeviceResponse("\n", ">", 2, remote_conn)
|
||||
|
||||
output = output + \
|
||||
cnos.enterEnableModeForDevice(enablePassword, 3, remote_conn)
|
||||
|
||||
# Make terminal length = 0
|
||||
output = output + \
|
||||
cnos.waitForDeviceResponse("terminal length 0\n", "#", 2, remote_conn)
|
||||
|
||||
# Go to config mode
|
||||
output = output + \
|
||||
cnos.waitForDeviceResponse(
|
||||
"configure d\n", "(config)#", 2, remote_conn)
|
||||
|
||||
# Send the CLi command
|
||||
output = output + cnos.vlagConfig(
|
||||
remote_conn, deviceType, "(config)#", 2, vlagArg1, vlagArg2, vlagArg3,
|
||||
vlagArg4)
|
||||
|
||||
# Save it into the file
|
||||
file = open(outputfile, "a")
|
||||
file.write(output)
|
||||
file.close()
|
||||
|
||||
# need to add logic to check when changes occur or not
|
||||
errorMsg = cnos.checkOutputForError(output)
|
||||
if(errorMsg is None):
|
||||
module.exit_json(changed=True, msg="vlag configurations accomplished")
|
||||
else:
|
||||
module.fail_json(msg=errorMsg)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
299
lib/ansible/modules/network/cnos/cnos_vlan.py
Normal file
299
lib/ansible/modules/network/cnos/cnos_vlan.py
Normal file
@@ -0,0 +1,299 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
#
|
||||
# Copyright (C) 2017 Lenovo, 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/>.
|
||||
#
|
||||
# Module to send VLAN commands to Lenovo Switches
|
||||
# Overloading aspect of vlan creation in a range is pending
|
||||
# Lenovo Networking
|
||||
#
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: cnos_vlan
|
||||
author: "Dave Kasberg (@dkasberg)"
|
||||
short_description: Manage VLAN resources and attributes on devices running Lenovo CNOS
|
||||
description:
|
||||
- This module allows you to work with VLAN related configurations. The
|
||||
operators used are overloaded to ensure control over switch VLAN
|
||||
configurations. The first level of VLAN configuration allows to set up the
|
||||
VLAN range, the VLAN tag persistence, a VLAN access map and access map
|
||||
filter. After passing this level, there are five VLAN arguments that will
|
||||
perform further configurations. They are vlanArg1, vlanArg2, vlanArg3,
|
||||
vlanArg4, and vlanArg5. The value of vlanArg1 will determine the way
|
||||
following arguments will be evaluated. For more details on how to use these
|
||||
arguments, see [Overloaded Variables].
|
||||
This module uses SSH to manage network device configuration.
|
||||
The results of the operation will be placed in a directory named 'results'
|
||||
that must be created by the user in their local directory to where the playbook is run.
|
||||
For more information about this module from Lenovo and customizing it usage for your
|
||||
use cases, please visit U(http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_vlan.html)
|
||||
version_added: "2.3"
|
||||
extends_documentation_fragment: cnos
|
||||
options:
|
||||
vlanArg1:
|
||||
description:
|
||||
- This is an overloaded vlan first argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: true
|
||||
default: null
|
||||
choices: [access-map, dot1q, filter, <1-3999> VLAN ID 1-3999 or range]
|
||||
vlanArg2:
|
||||
description:
|
||||
- This is an overloaded vlan second argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: false
|
||||
default: null
|
||||
choices: [VLAN Access Map name,egress-only,name, flood,state, ip]
|
||||
vlanArg3:
|
||||
description:
|
||||
- This is an overloaded vlan third argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: false
|
||||
default: null
|
||||
choices: [action, match, statistics, enter VLAN id or range of vlan, ascii name for the VLAN, ipv4 or ipv6, active or suspend, fast-leave,
|
||||
last-member-query-interval, mrouter, querier, querier-timeout, query-interval, query-max-response-time, report-suppression,
|
||||
robustness-variable, startup-query-count, startup-query-interval, static-group]
|
||||
vlanArg4:
|
||||
description:
|
||||
- This is an overloaded vlan fourth argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: false
|
||||
default: null
|
||||
choices: [drop or forward or redirect, ip or mac,Interval in seconds,ethernet, port-aggregation, Querier IP address,
|
||||
Querier Timeout in seconds, Query Interval in seconds, Query Max Response Time in seconds, Robustness Variable value,
|
||||
Number of queries sent at startup, Query Interval at startup]
|
||||
vlanArg5:
|
||||
description:
|
||||
- This is an overloaded vlan fifth argument. Usage of this argument can be found is the User Guide referenced above.
|
||||
required: false
|
||||
default: null
|
||||
choices: [access-list name, Slot/chassis number, Port Aggregation Number]
|
||||
|
||||
'''
|
||||
EXAMPLES = '''
|
||||
|
||||
Tasks: The following are examples of using the module cnos_vlan. These are written in the main.yml file of the tasks directory.
|
||||
---
|
||||
- name: Test Vlan - Create a vlan, name it
|
||||
cnos_vlan:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_vlan_{{ inventory_hostname }}_output.txt"
|
||||
vlanArg1: 13
|
||||
vlanArg2: "name"
|
||||
vlanArg3: "Anil"
|
||||
|
||||
- name: Test Vlan - Create a vlan, Flood configuration
|
||||
cnos_vlan:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_vlan_{{ inventory_hostname }}_output.txt"
|
||||
vlanArg1: 13
|
||||
vlanArg2: "flood"
|
||||
vlanArg3: "ipv4"
|
||||
|
||||
- name: Test Vlan - Create a vlan, State configuration
|
||||
cnos_vlan:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_vlan_{{ inventory_hostname }}_output.txt"
|
||||
vlanArg1: 13
|
||||
vlanArg2: "state"
|
||||
vlanArg3: "active"
|
||||
|
||||
- name: Test Vlan - VLAN Access map1
|
||||
cnos_vlan:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_vlan_{{ inventory_hostname }}_output.txt"
|
||||
vlanArg1: "access-map"
|
||||
vlanArg2: "Anil"
|
||||
vlanArg3: "statistics"
|
||||
|
||||
- name: Test Vlan - VLAN Accep Map2
|
||||
cnos_vlan:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_vlan_{{ inventory_hostname }}_output.txt"
|
||||
vlanArg1: "access-map"
|
||||
vlanArg2: "Anil"
|
||||
vlanArg3: "action"
|
||||
vlanArg4: "forward"
|
||||
|
||||
- name: Test Vlan - ip igmp snooping query interval
|
||||
cnos_vlan:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_vlan_{{ inventory_hostname }}_output.txt"
|
||||
vlanArg1: 13
|
||||
vlanArg2: "ip"
|
||||
vlanArg3: "query-interval"
|
||||
vlanArg4: 1313
|
||||
|
||||
- name: Test Vlan - ip igmp snooping mrouter interface port-aggregation 23
|
||||
cnos_vlan:
|
||||
host: "{{ inventory_hostname }}"
|
||||
username: "{{ hostvars[inventory_hostname]['username'] }}"
|
||||
password: "{{ hostvars[inventory_hostname]['password'] }}"
|
||||
deviceType: "{{ hostvars[inventory_hostname]['deviceType'] }}"
|
||||
enablePassword: "{{ hostvars[inventory_hostname]['enablePassword'] }}"
|
||||
outputfile: "./results/test_vlan_{{ inventory_hostname }}_output.txt"
|
||||
vlanArg1: 13
|
||||
vlanArg2: "ip"
|
||||
vlanArg3: "mrouter"
|
||||
vlanArg4: "port-aggregation"
|
||||
vlanArg5: 23
|
||||
|
||||
'''
|
||||
RETURN = '''
|
||||
msg:
|
||||
description: Success or failure message
|
||||
returned: always
|
||||
type: string
|
||||
sample: "VLAN configuration is accomplished"
|
||||
'''
|
||||
|
||||
import sys
|
||||
try:
|
||||
import paramiko
|
||||
HAS_PARAMIKO = True
|
||||
except ImportError:
|
||||
HAS_PARAMIKO = False
|
||||
import time
|
||||
import socket
|
||||
import array
|
||||
import json
|
||||
import time
|
||||
import re
|
||||
|
||||
try:
|
||||
from ansible.module_utils import cnos
|
||||
HAS_LIB = True
|
||||
except:
|
||||
HAS_LIB = False
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
def main():
|
||||
#
|
||||
# Define parameters for vlan creation entry
|
||||
#
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
outputfile=dict(required=True),
|
||||
host=dict(required=True),
|
||||
username=dict(required=True),
|
||||
password=dict(required=True, no_log=True),
|
||||
enablePassword=dict(required=False, no_log=True),
|
||||
deviceType=dict(required=True),
|
||||
vlanArg1=dict(required=True),
|
||||
vlanArg2=dict(required=False),
|
||||
vlanArg3=dict(required=False),
|
||||
vlanArg4=dict(required=False),
|
||||
vlanArg5=dict(required=False),),
|
||||
supports_check_mode=False)
|
||||
|
||||
username = module.params['username']
|
||||
password = module.params['password']
|
||||
enablePassword = module.params['enablePassword']
|
||||
vlanArg1 = module.params['vlanArg1']
|
||||
vlanArg2 = module.params['vlanArg2']
|
||||
vlanArg3 = module.params['vlanArg3']
|
||||
vlanArg4 = module.params['vlanArg4']
|
||||
vlanArg5 = module.params['vlanArg5']
|
||||
outputfile = module.params['outputfile']
|
||||
hostIP = module.params['host']
|
||||
deviceType = module.params['deviceType']
|
||||
|
||||
output = ""
|
||||
if not HAS_PARAMIKO:
|
||||
module.fail_json(msg='paramiko is required for this module')
|
||||
|
||||
# Create instance of SSHClient object
|
||||
remote_conn_pre = paramiko.SSHClient()
|
||||
|
||||
# Automatically add untrusted hosts (make sure okay for security policy in
|
||||
# your environment)
|
||||
remote_conn_pre.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
|
||||
# initiate SSH connection with the switch
|
||||
remote_conn_pre.connect(hostIP, username=username, password=password)
|
||||
time.sleep(2)
|
||||
|
||||
# Use invoke_shell to establish an 'interactive session'
|
||||
remote_conn = remote_conn_pre.invoke_shell()
|
||||
time.sleep(2)
|
||||
|
||||
# Enable and enter configure terminal then send command
|
||||
output = output + cnos.waitForDeviceResponse("\n", ">", 2, remote_conn)
|
||||
|
||||
output = output + \
|
||||
cnos.enterEnableModeForDevice(enablePassword, 3, remote_conn)
|
||||
|
||||
# Make terminal length = 0
|
||||
output = output + \
|
||||
cnos.waitForDeviceResponse("terminal length 0\n", "#", 2, remote_conn)
|
||||
|
||||
# Go to config mode
|
||||
output = output + \
|
||||
cnos.waitForDeviceResponse("conf d\n", "(config)#", 2, remote_conn)
|
||||
|
||||
# Send the CLi command
|
||||
output = output + \
|
||||
cnos.vlanConfig(
|
||||
remote_conn, deviceType, "(config)#", 2, vlanArg1, vlanArg2,
|
||||
vlanArg3, vlanArg4, vlanArg5)
|
||||
|
||||
# Save it into the file
|
||||
file = open(outputfile, "a")
|
||||
file.write(output)
|
||||
file.close()
|
||||
|
||||
# need to add logic to check when changes occur or not
|
||||
errorMsg = cnos.checkOutputForError(output)
|
||||
if(errorMsg is None):
|
||||
module.exit_json(changed=True, msg="VLAN configuration is accomplished")
|
||||
else:
|
||||
module.fail_json(msg=errorMsg)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user