mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Persistence connection for cnos_vlan (#42500)
* Changing Lenovo Inc to Lenovo and update License file to be consistent. * Changing cnos_vlan from paramiko to persistence connection of Ansible. Also talking care of CLI changes in CNOS commands with backward compatibility. * Fixing Validation issues * Trailing lines removal * Review comments of Gundalow are getting addressed. He mentioned only at one place for cnos.py. But I have covered the entire file. * Changes to incorporate Review comments from Qalthos * Removing configure terminal command from module code * Aligning with change in run_cnos_commands method changes * Editing cliconf for latest CNOS CLIs
This commit is contained in:
parent
1a0330488f
commit
0897e79bd1
6 changed files with 204 additions and 151 deletions
|
@ -162,6 +162,32 @@ def run_commands(module, commands, check_rc=True):
|
||||||
return responses
|
return responses
|
||||||
|
|
||||||
|
|
||||||
|
def run_cnos_commands(module, commands, check_rc=True):
|
||||||
|
retVal = ''
|
||||||
|
enter_config = {'command': 'configure terminal', 'prompt': None, 'answer': None}
|
||||||
|
exit_config = {'command': 'end', 'prompt': None, 'answer': None}
|
||||||
|
commands.insert(0, enter_config)
|
||||||
|
commands.append(exit_config)
|
||||||
|
for cmd in commands:
|
||||||
|
retVal = retVal + '>> ' + cmd['command'] + '\n'
|
||||||
|
try:
|
||||||
|
responses = run_commands(module, commands, check_rc)
|
||||||
|
for response in responses:
|
||||||
|
retVal = retVal + '<< ' + response + '\n'
|
||||||
|
except Exception as e:
|
||||||
|
errMsg = ''
|
||||||
|
if hasattr(e, 'message'):
|
||||||
|
errMsg = e.message
|
||||||
|
else:
|
||||||
|
errMsg = str(e)
|
||||||
|
# Exception in Exceptions
|
||||||
|
if 'VLAN_ACCESS_MAP' in errMsg:
|
||||||
|
return retVal + '<<' + errMsg + '\n'
|
||||||
|
# Add more here if required
|
||||||
|
retVal = retVal + '<< ' + 'Error-101 ' + errMsg + '\n'
|
||||||
|
return str(retVal)
|
||||||
|
|
||||||
|
|
||||||
def load_config(module, config):
|
def load_config(module, config):
|
||||||
try:
|
try:
|
||||||
conn = get_connection(module)
|
conn = get_connection(module)
|
||||||
|
@ -2187,29 +2213,29 @@ def bgpConfig(
|
||||||
# EOM
|
# EOM
|
||||||
|
|
||||||
|
|
||||||
def vlanConfig(
|
def vlanConfig(module, prompt, answer):
|
||||||
obj, deviceType, prompt, timeout, vlanArg1, vlanArg2, vlanArg3,
|
|
||||||
vlanArg4, vlanArg5):
|
|
||||||
|
|
||||||
retVal = ""
|
retVal = ''
|
||||||
# Wait time to get response from server
|
# Wait time to get response from server
|
||||||
timeout = timeout
|
vlanArg1 = module.params['vlanArg1']
|
||||||
|
vlanArg2 = module.params['vlanArg2']
|
||||||
|
vlanArg3 = module.params['vlanArg3']
|
||||||
|
vlanArg4 = module.params['vlanArg4']
|
||||||
|
vlanArg5 = module.params['vlanArg5']
|
||||||
|
deviceType = module.params['deviceType']
|
||||||
# vlan config command happens here.
|
# vlan config command happens here.
|
||||||
command = "vlan "
|
command = 'vlan '
|
||||||
|
|
||||||
if(vlanArg1 == "access-map"):
|
if(vlanArg1 == "access-map"):
|
||||||
# debugOutput("access-map ")
|
# debugOutput("access-map ")
|
||||||
command = command + vlanArg1 + " "
|
command = command + vlanArg1 + ' '
|
||||||
value = checkSanityofVariable(
|
value = checkSanityofVariable(
|
||||||
deviceType, "vlan_access_map_name", vlanArg2)
|
deviceType, "vlan_access_map_name", vlanArg2)
|
||||||
if(value == "ok"):
|
if(value == "ok"):
|
||||||
command = command + vlanArg2 + " \n"
|
command = command + vlanArg2
|
||||||
# debugOutput(command)
|
# debugOutput(command)
|
||||||
retVal = waitForDeviceResponse(
|
cmd = [{'command': command, 'prompt': None, 'answer': None}]
|
||||||
command, "(config-access-map)#", timeout, obj)
|
retVal = retVal + vlanAccessMapConfig(module, cmd)
|
||||||
retVal = retVal + vlanAccessMapConfig(
|
|
||||||
obj, deviceType, "(config-access-map)#", timeout, vlanArg3,
|
|
||||||
vlanArg4, vlanArg5)
|
|
||||||
return retVal
|
return retVal
|
||||||
else:
|
else:
|
||||||
retVal = "Error-130"
|
retVal = "Error-130"
|
||||||
|
@ -2244,7 +2270,7 @@ def vlanConfig(
|
||||||
if(value == "ok"):
|
if(value == "ok"):
|
||||||
command = command + vlanArg3
|
command = command + vlanArg3
|
||||||
else:
|
else:
|
||||||
retVal = "ERROR-133"
|
retVal = "Error-133"
|
||||||
return retVal
|
return retVal
|
||||||
else:
|
else:
|
||||||
retVal = "Error-132"
|
retVal = "Error-132"
|
||||||
|
@ -2253,37 +2279,34 @@ def vlanConfig(
|
||||||
else:
|
else:
|
||||||
value = checkSanityofVariable(deviceType, "vlan_id", vlanArg1)
|
value = checkSanityofVariable(deviceType, "vlan_id", vlanArg1)
|
||||||
if(value == "ok"):
|
if(value == "ok"):
|
||||||
retVal = createVlan(obj, deviceType, "(config-vlan)#",
|
retVal = createVlan(module, '(config-vlan)#', None)
|
||||||
timeout, vlanArg1, vlanArg2, vlanArg3,
|
|
||||||
vlanArg4, vlanArg5)
|
|
||||||
return retVal
|
return retVal
|
||||||
else:
|
else:
|
||||||
value = checkSanityofVariable(
|
value = checkSanityofVariable(
|
||||||
deviceType, "vlan_id_range", vlanArg1)
|
deviceType, "vlan_id_range", vlanArg1)
|
||||||
if(value == "ok"):
|
if(value == "ok"):
|
||||||
retVal = createVlan(obj, deviceType, "(config-vlan)#",
|
retVal = createVlan(module, '(config-vlan)#', None)
|
||||||
timeout, vlanArg1, vlanArg2, vlanArg3,
|
|
||||||
vlanArg4, vlanArg5)
|
|
||||||
return retVal
|
return retVal
|
||||||
retVal = "Error-133"
|
retVal = "Error-133"
|
||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
# debugOutput(command)
|
# debugOutput(command)
|
||||||
command = command + "\n"
|
cmd = [{'command': command, 'prompt': None, 'answer': None}]
|
||||||
# debugOutput(command)
|
retVal = retVal + str(run_cnos_commands(module, cmd))
|
||||||
retVal = retVal + waitForDeviceResponse(command, prompt, timeout, obj)
|
|
||||||
return retVal
|
return retVal
|
||||||
# EOM
|
# EOM
|
||||||
|
|
||||||
|
|
||||||
def vlanAccessMapConfig(
|
def vlanAccessMapConfig(module, cmd):
|
||||||
obj, deviceType, prompt, timeout, vlanArg3, vlanArg4, vlanArg5):
|
retVal = ''
|
||||||
retVal = ""
|
|
||||||
# Wait time to get response from server
|
# Wait time to get response from server
|
||||||
timeout = timeout
|
command = ''
|
||||||
command = ""
|
vlanArg3 = module.params['vlanArg3']
|
||||||
|
vlanArg4 = module.params['vlanArg4']
|
||||||
|
vlanArg5 = module.params['vlanArg5']
|
||||||
|
deviceType = module.params['deviceType']
|
||||||
if(vlanArg3 == "action"):
|
if(vlanArg3 == "action"):
|
||||||
command = command + vlanArg3 + " "
|
command = command + vlanArg3 + ' '
|
||||||
value = checkSanityofVariable(
|
value = checkSanityofVariable(
|
||||||
deviceType, "vlan_accessmap_action", vlanArg4)
|
deviceType, "vlan_accessmap_action", vlanArg4)
|
||||||
if(value == "ok"):
|
if(value == "ok"):
|
||||||
|
@ -2292,9 +2315,9 @@ def vlanAccessMapConfig(
|
||||||
retVal = "Error-135"
|
retVal = "Error-135"
|
||||||
return retVal
|
return retVal
|
||||||
elif(vlanArg3 == "match"):
|
elif(vlanArg3 == "match"):
|
||||||
command = command + vlanArg3 + " "
|
command = command + vlanArg3 + ' '
|
||||||
if(vlanArg4 == "ip" or vlanArg4 == "mac"):
|
if(vlanArg4 == "ip" or vlanArg4 == "mac"):
|
||||||
command = command + vlanArg4 + " address "
|
command = command + vlanArg4 + ' address '
|
||||||
value = checkSanityofVariable(
|
value = checkSanityofVariable(
|
||||||
deviceType, "vlan_access_map_name", vlanArg5)
|
deviceType, "vlan_access_map_name", vlanArg5)
|
||||||
if(value == "ok"):
|
if(value == "ok"):
|
||||||
|
@ -2311,18 +2334,24 @@ def vlanAccessMapConfig(
|
||||||
retVal = "Error-138"
|
retVal = "Error-138"
|
||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
command = command + "\n"
|
inner_cmd = [{'command': command, 'prompt': None, 'answer': None}]
|
||||||
|
cmd.extend(inner_cmd)
|
||||||
|
retVal = retVal + str(run_cnos_commands(module, cmd))
|
||||||
# debugOutput(command)
|
# debugOutput(command)
|
||||||
retVal = retVal + waitForDeviceResponse(command, prompt, timeout, obj)
|
|
||||||
return retVal
|
return retVal
|
||||||
# EOM
|
# EOM
|
||||||
|
|
||||||
|
|
||||||
def checkVlanNameNotAssigned(
|
def checkVlanNameNotAssigned(module, prompt, answer):
|
||||||
obj, deviceType, prompt, timeout, vlanId, vlanName):
|
|
||||||
retVal = "ok"
|
retVal = "ok"
|
||||||
command = "display vlan id " + vlanId + " \n"
|
vlanId = module.params['vlanArg1']
|
||||||
retVal = waitForDeviceResponse(command, prompt, timeout, obj)
|
vlanName = module.params['vlanArg3']
|
||||||
|
command = "show vlan id " + vlanId
|
||||||
|
cmd = [{'command': command, 'prompt': None, 'answer': None}]
|
||||||
|
retVal = str(run_cnos_commands(module, cmd))
|
||||||
|
if(retVal.find('Error') != -1):
|
||||||
|
command = "display vlan id " + vlanId
|
||||||
|
retVal = str(run_cnos_commands(module, cmd))
|
||||||
if(retVal.find(vlanName) != -1):
|
if(retVal.find(vlanName) != -1):
|
||||||
return "Nok"
|
return "Nok"
|
||||||
else:
|
else:
|
||||||
|
@ -2331,25 +2360,30 @@ def checkVlanNameNotAssigned(
|
||||||
|
|
||||||
|
|
||||||
# Utility Method to create vlan
|
# Utility Method to create vlan
|
||||||
def createVlan(
|
def createVlan(module, prompt, answer):
|
||||||
obj, deviceType, prompt, timeout, vlanArg1, vlanArg2, vlanArg3,
|
|
||||||
vlanArg4, vlanArg5):
|
|
||||||
|
|
||||||
# vlan config command happens here. It creates if not present
|
# vlan config command happens here. It creates if not present
|
||||||
command = "vlan " + vlanArg1 + "\n"
|
vlanArg1 = module.params['vlanArg1']
|
||||||
|
vlanArg2 = module.params['vlanArg2']
|
||||||
|
vlanArg3 = module.params['vlanArg3']
|
||||||
|
vlanArg4 = module.params['vlanArg4']
|
||||||
|
vlanArg5 = module.params['vlanArg5']
|
||||||
|
deviceType = module.params['deviceType']
|
||||||
|
retVal = ''
|
||||||
|
command = 'vlan ' + vlanArg1
|
||||||
# debugOutput(command)
|
# debugOutput(command)
|
||||||
retVal = waitForDeviceResponse(command, prompt, timeout, obj)
|
cmd = [{'command': command, 'prompt': None, 'answer': None}]
|
||||||
command = ""
|
command = ""
|
||||||
if(vlanArg2 == "name"):
|
if(vlanArg2 == "name"):
|
||||||
# debugOutput("name")
|
# debugOutput("name")
|
||||||
command = vlanArg2 + " "
|
command = vlanArg2 + " "
|
||||||
value = checkSanityofVariable(deviceType, "vlan_name", vlanArg3)
|
value = checkSanityofVariable(deviceType, "vlan_name", vlanArg3)
|
||||||
if(value == "ok"):
|
if(value == "ok"):
|
||||||
value = checkVlanNameNotAssigned(obj, deviceType, prompt, timeout,
|
value = checkVlanNameNotAssigned(module, prompt, answer)
|
||||||
vlanArg1, vlanArg3)
|
|
||||||
if(value == "ok"):
|
if(value == "ok"):
|
||||||
command = command + vlanArg3
|
command = command + vlanArg3
|
||||||
else:
|
else:
|
||||||
|
retVal = retVal + 'VLAN Name is already assigned \n'
|
||||||
command = "\n"
|
command = "\n"
|
||||||
else:
|
else:
|
||||||
retVal = "Error-139"
|
retVal = "Error-139"
|
||||||
|
@ -2470,13 +2504,6 @@ def createVlan(
|
||||||
retVal = "Error-149"
|
retVal = "Error-149"
|
||||||
return retVal
|
return retVal
|
||||||
elif (vlanArg3 == "static-group"):
|
elif (vlanArg3 == "static-group"):
|
||||||
# debugOutput("static-group")
|
|
||||||
# command = command + vlanArg3 + " "
|
|
||||||
# value = checkSanityofVariable(deviceType, variableId, vlanArg4)
|
|
||||||
# if(value == "ok"):
|
|
||||||
# command = command + vlanArg4
|
|
||||||
|
|
||||||
# else :
|
|
||||||
retVal = "Error-102"
|
retVal = "Error-102"
|
||||||
return retVal
|
return retVal
|
||||||
elif (vlanArg3 == "version"):
|
elif (vlanArg3 == "version"):
|
||||||
|
@ -2519,15 +2546,10 @@ def createVlan(
|
||||||
else:
|
else:
|
||||||
retVal = "Error-154"
|
retVal = "Error-154"
|
||||||
return retVal
|
return retVal
|
||||||
command = command + "\n"
|
inner_cmd = [{'command': command, 'prompt': None, 'answer': None}]
|
||||||
|
cmd.extend(inner_cmd)
|
||||||
|
retVal = retVal + str(run_cnos_commands(module, cmd))
|
||||||
# debugOutput(command)
|
# debugOutput(command)
|
||||||
retVal = retVal + "\n" + \
|
|
||||||
waitForDeviceResponse(command, prompt, timeout, obj)
|
|
||||||
# Come back to config mode
|
|
||||||
command = "exit \n"
|
|
||||||
# debugOutput(command)
|
|
||||||
retVal = retVal + waitForDeviceResponse(command, "(config)#", timeout, obj)
|
|
||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
# EOM
|
# EOM
|
||||||
|
|
||||||
|
@ -2771,7 +2793,7 @@ def doSecureStartupConfigBackUp(
|
||||||
username + "@" + server + "/" + confPath + " vrf management\n"
|
username + "@" + server + "/" + confPath + " vrf management\n"
|
||||||
# debugOutput(command)
|
# debugOutput(command)
|
||||||
response = waitForDeviceResponse(command, "(yes/no)", 3, obj)
|
response = waitForDeviceResponse(command, "(yes/no)", 3, obj)
|
||||||
if(response.lower().find("error-101")):
|
if(response.lower().find('error-101')):
|
||||||
command = password + "\n"
|
command = password + "\n"
|
||||||
retVal = retVal + waitForDeviceResponse(command, "#", timeout, obj)
|
retVal = retVal + waitForDeviceResponse(command, "#", timeout, obj)
|
||||||
return retVal
|
return retVal
|
||||||
|
@ -2874,7 +2896,7 @@ def doSecureStartUpConfigRollback(
|
||||||
|
|
||||||
# debugOutput(command)
|
# debugOutput(command)
|
||||||
response = waitForDeviceResponse(command, "(yes/no)", 3, obj)
|
response = waitForDeviceResponse(command, "(yes/no)", 3, obj)
|
||||||
if(response.lower().find("error-101")):
|
if(response.lower().find('error-101')):
|
||||||
command = password + "\n"
|
command = password + "\n"
|
||||||
retVal = retVal + waitForDeviceResponse(command, "[n]", timeout, obj)
|
retVal = retVal + waitForDeviceResponse(command, "[n]", timeout, obj)
|
||||||
command = "y\n"
|
command = "y\n"
|
||||||
|
@ -2972,7 +2994,7 @@ def doSecureRunningConfigBackUp(
|
||||||
username + "@" + server + "/" + confPath + " vrf management\n"
|
username + "@" + server + "/" + confPath + " vrf management\n"
|
||||||
# debugOutput(command)
|
# debugOutput(command)
|
||||||
response = waitForDeviceResponse(command, "(yes/no)", 3, obj)
|
response = waitForDeviceResponse(command, "(yes/no)", 3, obj)
|
||||||
if(response.lower().find("error-101")):
|
if(response.lower().find('error-101')):
|
||||||
command = password + "\n"
|
command = password + "\n"
|
||||||
retVal = retVal + waitForDeviceResponse(command, "#", timeout, obj)
|
retVal = retVal + waitForDeviceResponse(command, "#", timeout, obj)
|
||||||
return retVal
|
return retVal
|
||||||
|
@ -3071,7 +3093,7 @@ def doSecureRunningConfigRollback(
|
||||||
|
|
||||||
# debugOutput(command)
|
# debugOutput(command)
|
||||||
response = waitForDeviceResponse(command, "(yes/no)", 3, obj)
|
response = waitForDeviceResponse(command, "(yes/no)", 3, obj)
|
||||||
if(response.lower().find("error-101")):
|
if(response.lower().find('error-101')):
|
||||||
command = password + "\n"
|
command = password + "\n"
|
||||||
retVal = retVal + waitForDeviceResponse(command, "#", timeout, obj)
|
retVal = retVal + waitForDeviceResponse(command, "#", timeout, obj)
|
||||||
return retVal
|
return retVal
|
||||||
|
@ -3135,7 +3157,7 @@ def doImageTransfer(
|
||||||
return "Error-110"
|
return "Error-110"
|
||||||
# debugOutput(command)
|
# debugOutput(command)
|
||||||
response = waitForDeviceResponse(command, "[n]", 3, obj)
|
response = waitForDeviceResponse(command, "[n]", 3, obj)
|
||||||
if(response.lower().find("error-101")):
|
if(response.lower().find('error-101')):
|
||||||
retVal = retVal
|
retVal = retVal
|
||||||
else:
|
else:
|
||||||
retVal = retVal + response
|
retVal = retVal + response
|
||||||
|
@ -3185,7 +3207,7 @@ def doSecureImageTransfer(
|
||||||
server + "/" + imgPath + " system-image " + type + " vrf management \n"
|
server + "/" + imgPath + " system-image " + type + " vrf management \n"
|
||||||
# debugOutput(command)
|
# debugOutput(command)
|
||||||
response = waitForDeviceResponse(command, "[n]", 3, obj)
|
response = waitForDeviceResponse(command, "[n]", 3, obj)
|
||||||
if(response.lower().find("error-101")):
|
if(response.lower().find('error-101')):
|
||||||
retVal = retVal
|
retVal = retVal
|
||||||
else:
|
else:
|
||||||
retVal = retVal + response
|
retVal = retVal + response
|
||||||
|
@ -3194,7 +3216,7 @@ def doSecureImageTransfer(
|
||||||
command = "y\n"
|
command = "y\n"
|
||||||
# debugOutput(command)
|
# debugOutput(command)
|
||||||
response = waitForDeviceResponse(command, "(yes/no)?", 3, obj)
|
response = waitForDeviceResponse(command, "(yes/no)?", 3, obj)
|
||||||
if(response.lower().find("error-101")):
|
if(response.lower().find('error-101')):
|
||||||
retVal = retVal
|
retVal = retVal
|
||||||
else:
|
else:
|
||||||
retVal = retVal + response
|
retVal = retVal + response
|
||||||
|
@ -3208,7 +3230,7 @@ def doSecureImageTransfer(
|
||||||
command = "y\n"
|
command = "y\n"
|
||||||
# debugOutput(command)
|
# debugOutput(command)
|
||||||
response = waitForDeviceResponse(command, "(yes/no)?", 3, obj)
|
response = waitForDeviceResponse(command, "(yes/no)?", 3, obj)
|
||||||
if(response.lower().find("error-101")):
|
if(response.lower().find('error-101')):
|
||||||
retVal = retVal
|
retVal = retVal
|
||||||
else:
|
else:
|
||||||
retVal = retVal + response
|
retVal = retVal + response
|
||||||
|
@ -3320,19 +3342,19 @@ def waitForDeviceResponse(command, prompt, timeout, obj):
|
||||||
|
|
||||||
def checkOutputForError(output):
|
def checkOutputForError(output):
|
||||||
retVal = ""
|
retVal = ""
|
||||||
index = output.lower().find("error")
|
index = output.lower().find('error')
|
||||||
startIndex = index + 6
|
startIndex = index + 6
|
||||||
if(index == -1):
|
if(index == -1):
|
||||||
index = output.lower().find("invalid")
|
index = output.lower().find('invalid')
|
||||||
startIndex = index + 8
|
startIndex = index + 8
|
||||||
if(index == -1):
|
if(index == -1):
|
||||||
index = output.lower().find("cannot be enabled in l2 interface")
|
index = output.lower().find('cannot be enabled in l2 interface')
|
||||||
startIndex = index + 34
|
startIndex = index + 34
|
||||||
if(index == -1):
|
if(index == -1):
|
||||||
index = output.lower().find("incorrect")
|
index = output.lower().find('incorrect')
|
||||||
startIndex = index + 10
|
startIndex = index + 10
|
||||||
if(index == -1):
|
if(index == -1):
|
||||||
index = output.lower().find("failure")
|
index = output.lower().find('failure')
|
||||||
startIndex = index + 8
|
startIndex = index + 8
|
||||||
if(index == -1):
|
if(index == -1):
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -43,13 +43,12 @@ description:
|
||||||
filter. After passing this level, there are five VLAN arguments that will
|
filter. After passing this level, there are five VLAN arguments that will
|
||||||
perform further configurations. They are vlanArg1, vlanArg2, vlanArg3,
|
perform further configurations. They are vlanArg1, vlanArg2, vlanArg3,
|
||||||
vlanArg4, and vlanArg5. The value of vlanArg1 will determine the way
|
vlanArg4, and vlanArg5. The value of vlanArg1 will determine the way
|
||||||
following arguments will be evaluated. For more details on how to use these
|
following arguments will be evaluated. This module uses SSH to manage network
|
||||||
arguments, see [Overloaded Variables].
|
device configuration. The results of the operation will be placed in a directory
|
||||||
This module uses SSH to manage network device configuration.
|
named 'results' that must be created by the user in their local directory to
|
||||||
The results of the operation will be placed in a directory named 'results'
|
where the playbook is run. For more information about this module from Lenovo and
|
||||||
that must be created by the user in their local directory to where the playbook is run.
|
customizing it usage for your use cases,
|
||||||
For more information about this module from Lenovo and customizing it usage for your
|
please visit U(http://systemx.lenovofiles.com/help/index.jsp?topic=%2Fcom.lenovo.switchmgt.ansible.doc%2Fcnos_vlan.html)
|
||||||
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"
|
version_added: "2.3"
|
||||||
extends_documentation_fragment: cnos
|
extends_documentation_fragment: cnos
|
||||||
options:
|
options:
|
||||||
|
@ -182,24 +181,17 @@ msg:
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
try:
|
|
||||||
import paramiko
|
|
||||||
HAS_PARAMIKO = True
|
|
||||||
except ImportError:
|
|
||||||
HAS_PARAMIKO = False
|
|
||||||
import time
|
import time
|
||||||
import socket
|
import socket
|
||||||
import array
|
import array
|
||||||
import json
|
import json
|
||||||
import time
|
import time
|
||||||
import re
|
import re
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from ansible.module_utils.network.cnos import cnos
|
from ansible.module_utils.network.cnos import cnos
|
||||||
HAS_LIB = True
|
HAS_LIB = True
|
||||||
except:
|
except:
|
||||||
HAS_LIB = False
|
HAS_LIB = False
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
|
@ -223,58 +215,14 @@ def main():
|
||||||
vlanArg5=dict(required=False),),
|
vlanArg5=dict(required=False),),
|
||||||
supports_check_mode=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']
|
outputfile = module.params['outputfile']
|
||||||
hostIP = module.params['host']
|
|
||||||
deviceType = module.params['deviceType']
|
|
||||||
|
|
||||||
output = ""
|
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 device\n", "(config)#", 2, remote_conn)
|
|
||||||
|
|
||||||
# Send the CLi command
|
# Send the CLi command
|
||||||
output = output + \
|
output = output + str(cnos.vlanConfig(module, "(config)#", None))
|
||||||
cnos.vlanConfig(
|
|
||||||
remote_conn, deviceType, "(config)#", 2, vlanArg1, vlanArg2,
|
|
||||||
vlanArg3, vlanArg4, vlanArg5)
|
|
||||||
|
|
||||||
# Save it into the file
|
# Save it operation details into the file
|
||||||
file = open(outputfile, "a")
|
file = open(outputfile, "a")
|
||||||
file.write(output)
|
file.write(output)
|
||||||
file.close()
|
file.close()
|
||||||
|
@ -282,7 +230,8 @@ def main():
|
||||||
# need to add logic to check when changes occur or not
|
# need to add logic to check when changes occur or not
|
||||||
errorMsg = cnos.checkOutputForError(output)
|
errorMsg = cnos.checkOutputForError(output)
|
||||||
if(errorMsg is None):
|
if(errorMsg is None):
|
||||||
module.exit_json(changed=True, msg="VLAN configuration is accomplished")
|
module.exit_json(changed=True,
|
||||||
|
msg="VLAN configuration is accomplished")
|
||||||
else:
|
else:
|
||||||
module.fail_json(msg=errorMsg)
|
module.fail_json(msg=errorMsg)
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
#
|
||||||
# Module to Collect facts from Lenovo Switches running Lenovo ENOS commands
|
# Module to Collect facts from Lenovo Switches running Lenovo ENOS commands
|
||||||
# Lenovo Networking
|
# Lenovo Networking
|
||||||
#
|
#
|
||||||
|
|
|
@ -32,39 +32,52 @@ class Cliconf(CliconfBase):
|
||||||
device_info = {}
|
device_info = {}
|
||||||
|
|
||||||
device_info['network_os'] = 'cnos'
|
device_info['network_os'] = 'cnos'
|
||||||
reply = self.get(b'display version')
|
reply = self.get(b'show sys-info')
|
||||||
data = to_text(reply, errors='surrogate_or_strict').strip()
|
data = to_text(reply, errors='surrogate_or_strict').strip()
|
||||||
|
host = self.get(b'show hostname')
|
||||||
match = re.search(r'^System version: (.*?) ', data, re.M | re.I)
|
hostname = to_text(host, errors='surrogate_or_strict').strip()
|
||||||
if match:
|
if data:
|
||||||
device_info['network_os_version'] = match.group(1)
|
device_info['network_os_version'] = self.parse_version(data)
|
||||||
|
device_info['network_os_model'] = self.parse_model(data)
|
||||||
match = re.search(r'^Lenovo RackSwitch (\S+)', data, re.M | re.I)
|
device_info['network_os_hostname'] = hostname
|
||||||
if match:
|
|
||||||
device_info['network_os_model'] = match.group(1)
|
|
||||||
|
|
||||||
match = re.search(r'^Device name: (.*?) ', data, re.M | re.I)
|
|
||||||
if match:
|
|
||||||
device_info['network_os_hostname'] = match.group(1)
|
|
||||||
else:
|
|
||||||
device_info['network_os_hostname'] = "NA"
|
|
||||||
|
|
||||||
return device_info
|
return device_info
|
||||||
|
|
||||||
|
def parse_version(self, data):
|
||||||
|
for line in data.split('\n'):
|
||||||
|
line = line.strip()
|
||||||
|
match = re.match(r'System Software Revision (.*?)',
|
||||||
|
line, re.M | re.I)
|
||||||
|
if match:
|
||||||
|
vers = line.split(':')
|
||||||
|
ver = vers[1].strip()
|
||||||
|
return ver
|
||||||
|
return "NA"
|
||||||
|
|
||||||
|
def parse_model(self, data):
|
||||||
|
for line in data.split('\n'):
|
||||||
|
line = line.strip()
|
||||||
|
match = re.match(r'System Model (.*?)', line, re.M | re.I)
|
||||||
|
if match:
|
||||||
|
mdls = line.split(':')
|
||||||
|
mdl = mdls[1].strip()
|
||||||
|
return mdl
|
||||||
|
return "NA"
|
||||||
|
|
||||||
@enable_mode
|
@enable_mode
|
||||||
def get_config(self, source='running', format='text'):
|
def get_config(self, source='running', format='text'):
|
||||||
if source not in ('running', 'startup'):
|
if source not in ('running', 'startup'):
|
||||||
msg = "fetching configuration from %s is not supported"
|
msg = "fetching configuration from %s is not supported"
|
||||||
return self.invalid_params(msg % source)
|
return self.invalid_params(msg % source)
|
||||||
if source == 'running':
|
if source == 'running':
|
||||||
cmd = b'display running-config'
|
cmd = b'show running-config'
|
||||||
else:
|
else:
|
||||||
cmd = b'display startup-config'
|
cmd = b'show startup-config'
|
||||||
return self.send_command(cmd)
|
return self.send_command(cmd)
|
||||||
|
|
||||||
@enable_mode
|
@enable_mode
|
||||||
def edit_config(self, command):
|
def edit_config(self, command):
|
||||||
for cmd in chain([b'configure device'], to_list(command), [b'end']):
|
for cmd in chain([b'configure terminal'], to_list(command), [b'end']):
|
||||||
self.send_command(cmd)
|
self.send_command(cmd)
|
||||||
|
|
||||||
def get(self, command, prompt=None, answer=None, sendonly=False):
|
def get(self, command, prompt=None, answer=None, sendonly=False):
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
VLAN Name Status IPMC FLOOD Ports
|
||||||
|
======== ================================ ======= ========== ===================
|
||||||
|
1 default ACTIVE IPv6
|
||||||
|
Ethernet1/2(u)
|
||||||
|
Ethernet1/3(t)
|
||||||
|
Ethernet1/4(t)
|
||||||
|
Ethernet1/9(u)
|
||||||
|
Ethernet1/10(u)
|
||||||
|
Ethernet1/14(u)
|
||||||
|
Ethernet1/15(u)
|
||||||
|
Ethernet1/16(u)
|
||||||
|
Ethernet1/17(u)
|
||||||
|
13 anil ACTIVE IPv4,IPv6
|
||||||
|
po13(t)
|
||||||
|
po17(t)
|
||||||
|
po100(t)
|
||||||
|
po1003(t)
|
||||||
|
po1004(t)
|
||||||
|
Ethernet1/3(t)
|
||||||
|
Ethernet1/4(t)
|
||||||
|
|
47
test/units/modules/network/cnos/test_cnos_vlan.py
Normal file
47
test/units/modules/network/cnos/test_cnos_vlan.py
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import json
|
||||||
|
from ansible.compat.tests.mock import patch
|
||||||
|
from ansible.modules.network.cnos import cnos_vlan
|
||||||
|
from units.modules.utils import set_module_args
|
||||||
|
from .cnos_module import TestCnosModule, load_fixture
|
||||||
|
|
||||||
|
|
||||||
|
class TestCnosVlanModule(TestCnosModule):
|
||||||
|
|
||||||
|
module = cnos_vlan
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestCnosVlanModule, self).setUp()
|
||||||
|
|
||||||
|
self.mock_run_cnos_commands = patch('ansible.module_utils.network.cnos.cnos.run_cnos_commands')
|
||||||
|
self.run_cnos_commands = self.mock_run_cnos_commands.start()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
super(TestCnosVlanModule, self).tearDown()
|
||||||
|
self.mock_run_cnos_commands.stop()
|
||||||
|
|
||||||
|
def load_fixtures(self, commands=None, transport='cli'):
|
||||||
|
self.run_cnos_commands.return_value = [load_fixture('cnos_vlan_config.cfg')]
|
||||||
|
|
||||||
|
def test_cnos_vlan_create(self):
|
||||||
|
set_module_args({'username': 'admin', 'password': 'pass',
|
||||||
|
'host': '10.241.107.39', 'deviceType': 'g8272_cnos',
|
||||||
|
'outputfile': 'test.log', 'vlanArg1': '13',
|
||||||
|
'vlanArg2': 'name', 'vlanArg3': 'anil'})
|
||||||
|
result = self.execute_module(changed=True)
|
||||||
|
file = open('Anil.txt', "a")
|
||||||
|
file.write(str(result))
|
||||||
|
file.close()
|
||||||
|
expected_result = 'VLAN configuration is accomplished'
|
||||||
|
self.assertEqual(result['msg'], expected_result)
|
||||||
|
|
||||||
|
def test_cnos_vlan_state(self):
|
||||||
|
set_module_args({'username': 'admin', 'password': 'pass',
|
||||||
|
'host': '10.241.107.39', 'deviceType': 'g8272_cnos',
|
||||||
|
'outputfile': 'test.log', 'vlanArg1': '13',
|
||||||
|
'vlanArg2': 'state', 'vlanArg3': 'active'})
|
||||||
|
result = self.execute_module(changed=True)
|
||||||
|
expected_result = 'VLAN configuration is accomplished'
|
||||||
|
self.assertEqual(result['msg'], expected_result)
|
Loading…
Reference in a new issue