ktbyers / netmiko

Multi-vendor library to simplify Paramiko SSH connections to network devices
MIT License
3.55k stars 1.3k forks source link

change default_enter behavior for Aruba driver #890

Closed MikeJurecki closed 6 years ago

MikeJurecki commented 6 years ago

In reference to "how to hit enter after a send_command #330" you offered a solution to respond to a router prompt. I am having an issue in changing a password, when manually performing this it prompts for a Password: and for you to re-enter the password as seen below. The solution that you offered did not work for me and after looking at the logs it looks to be sending the first password successfully but it it not reading the prompt for the second password.

Any code examples or solutions that you can provide would be amazing.

Manual Example:

(exampledevice1) (config) #mgmt-user admin root              
Password:********
Re-Type password:********

My Python Code:

net_connect.config_mode()

command = 'mgmt-user admin root'
aruba_pass = 'examplepassword'

configure4 = net_connect.send_command_timing(command)
        if 'Password:' in configure4:
            configure4 += net_connect.send_command_timing(aruba_pass)
        if 'password:' in configure4:
            configure4 += net_connect.send_command_timing(aruba_pass)

net_connect.exit_config_mode()

output2 = net_connect.save_config()

I have tried several different ways and it still wont work, any help would be greatly appreciated.

ktbyers commented 6 years ago

How about this:

net_connect.config_mode()

command = 'mgmt-user admin root'
aruba_pass = 'examplepassword'

output = net_connect.send_command_timing(command)
if 'Password:' in output:
    new_output = net_connect.send_command_timing(aruba_pass)

if 'Re-Type password' in new_output:
    net_connect.send_command_timing(aruba_pass)

net_connect.exit_config_mode()

output2 = net_connect.save_config()
ktbyers commented 6 years ago

I didn't see an issue with what you originally posted besides your indentation is invalid.

MikeJurecki commented 6 years ago

In my script the indentation is actually good, my copy and paste must have messed it up. Oddly it doesnt work, I will post my whole script below. Note I have a lot of commented out lines from other things I tried.

MikeJurecki commented 6 years ago
import netmiko
from datetime import datetime
from shutil import copy
import os
from os import listdir
from os.path import isfile, join
import logging
import time
import threading

run_date = datetime.today().date()
run_date = str(run_date)
run_time = datetime.now().time()
run_time = str(run_time)
run_time = run_time[:-7]
run_time = run_time.replace(':', '.')

logging.basicConfig(filename='Aruba_password_' + run_time + '.log', filemode='w', level=logging.DEBUG)

creds = []
with open('./creds/cred.txt', 'r') as file:
    creds = [line.strip() for line in file]

ios_ver = 'arubaos'
username = creds[0]
password = creds[1]

orig_path = './'
backup_path = './backups/'
postcap_path = './postcap/'
changes_path = './changes/'
logs_path = './logs/'

HOSTS = open('./hostlist/hostlist.txt', 'r')

HOST_FILE = []
for host1 in HOSTS:
    host1 = host1.rstrip('\n')
    if host1 == '':
        print('')  # Skips any blank lines
    else:
        HOST_FILE.append(host1)

HOSTS.close()

failed_list = []

# PENDING: Add in Multithread Function

def thread_login(u, p):
    threads = []
    for ipaddress in HOST_FILE:
        t = threading.Thread(target=main_thread, args=(ipaddress, u, p,), )
        t.start()
        threads.append(t)
        print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
        print('STARTING NEW THREAD - IP ADDRESS:', ipaddress)
        print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
        time.sleep(4)

    for thread in threads:
        thread.join()

def main_thread(ipaddress, u, p):  

    current_time = datetime.now().time()
    current_time = str(current_time)
    print('Starting Change', ipaddress, current_time)

    SSH_Device = {
        'device_type': 'aruba_os',
        'ip': ipaddress,
        'username': u,
        'password': p,
        'secret': p
    }

    try:
        net_connect = netmiko.ConnectHandler(**SSH_Device)

        net_connect.disable_paging()

        #if not net_connect.check_enable_mode():
        #    net_connect.enable()

    except Exception as e:
        e = str(e)
        failed = 'Connect Fail: ' + ipaddress + ':  ' + e
        failed_list.append(failed)
        print(e)

    try:

        outputfilename = ipaddress + '_Change_' + run_date + run_time + '.txt'
        outputfile = open(outputfilename, 'w')

        outputfile.write('#### ' + ipaddress + ' ---- ' + run_time + '####\n')

        # INFO: Gathering VLAN Information, Generating Lists
        outputfile.write('###\n')
        outputfile.write('###\n')
        outputfile.write('###\n')

        # INFO: Starting here we are determining if we need to apply the config or not.

        #file = './scripts/main_script.txt'
        #commandfile = open(file, 'r')

        net_connect.config_mode()

        command = 'mgmt-user admin root'
        aruba_pass = 'ExamplePassword'

        # I tried this first - It did not change the password
        # configure4 = net_connect.send_command_expect(command)
        # configure5 = net_connect.send_command_expect(aruba_pass)
        # configure6 = net_connect.send_command_expect(aruba_pass)

        # This is what I got from you and it also did not change the password
        configure4 = net_connect.send_command_timing(command)
        print(configure4)
        if 'Password:' in configure4:
            configure4 += net_connect.send_command_timing(aruba_pass)

        if 'password:' in configure4:
            configure4 += net_connect.send_command_timing(aruba_pass)

        print('Configuration Applied')
        print('configure4', configure4)
        #print('configure5', configure5)
        #print('configure6', configure6)
        outputfile.write(configure4 + '\n')
        #outputfile.write(configure5 + '\n')
        #outputfile.write(configure6 + '\n')

        outputfile.write('###\n')
        outputfile.write('###\n')
        print('----')

        # INFO: Saving configuration
        outputfile.write('###\n')
        outputfile.write('###Saving Configuration\n')
        print(ipaddress, str(datetime.now().time()), 'Saving Configuration')

        net_connect.exit_config_mode()

        output2 = net_connect.save_config()
        outputfile.write(output2 + '\n')
        print(ipaddress, str(datetime.now().time()), output2)
        print('----')

        outputfile.close()

    except Exception as e:
        e = str(e)
        failed = 'Connect Fail: ' + ipaddress + ':  ' + e
        failed_list.append(failed)
        print(e)

thread_login(u=username, p=password)  

# INFO: This is moving all files to correct directory
filelist = [f for f in listdir(orig_path) if isfile(join(orig_path, f))]
# Moving postcap files
for item in filelist:
    try:
        filename = orig_path + item
        if item.startswith("postcap"):
            copy(filename, postcap_path)
            os.remove(os.path.join(orig_path, item))
    except:
        continue

    # Moving Backup Files
for item in filelist:
    try:
        filename = orig_path + item
        if item.endswith(".cfg"):
            copy(filename, backup_path)
            os.remove(os.path.join(orig_path, item))
    except:
        continue

for item in filelist:
    try:
        filename = orig_path + item
        if item.endswith(".txt"):
            copy(filename, changes_path)
            os.remove(os.path.join(orig_path, item))
    except:
        continue

    # Moving Change Files

for item in filelist:

    try:
         filename2 = orig_path + item
         if item.endswith(".log"):
             copy(filename2, logs_path)
             os.remove(os.path.join(orig_path, item))
    except:
        continue

# INFO: Creates failed file for all exceptions
failedfile = 'FailedFile.txt'
failedfile2 = open(failedfile, 'w')
c = 1
for item in failed_list:
    failedfile2.write(str(c) + '. ' + item + '\n')
    c += 1

failedfile2.close()

# INFO: End of Script
end_time = datetime.now().time()
end_time = str(end_time)
end_time = end_time[:-7]
end_time = end_time.replace(':', '.')

print('Start Time:', run_time)
print('End time:', end_time)
MikeJurecki commented 6 years ago

In your code you do not assign the output to a variable like I do, do you think that is the problem?

ktbyers commented 6 years ago

I don't think that assignment should matter.

I would separate the part you are having issues with to a separate program (so you can isolate the issue).

        configure4 = net_connect.send_command_timing(command)

        if 'Password:' in configure4:
            print("Here...password1")
            configure4 += net_connect.send_command_timing(aruba_pass)

        if 'password:' in configure4:
            print("Here...password2")
            configure4 += net_connect.send_command_timing(aruba_pass)

        print(configure4)

And see what you see (to see if you can isolate the issue).

MikeJurecki commented 6 years ago

After trying a few things I found some interesting changes in the logs. It appears that it does enter the first password however it does not see the "Re-Type password:" prompt. I do not think that it is sending the enter command after the first "Password:" prompt.

You can see the ***** where it is entering the password but I think that it is appending '\n' to the password which is why we are not seeing the second prompt for re-entering the password.

So new question would be, is there a way to send an action such as hitting the enter key mid command without using '\n'? If so that may be the fix.

DEBUG:netmiko:write_channel: b'config term\n'
DEBUG:netmiko:Pattern is: \(usa\-exampleWLC
DEBUG:netmiko:_read_channel_expect read_data: configure ter
DEBUG:netmiko:_read_channel_expect read_data: m

Enter Configuration commands, one per line. End with CNTL/Z

(usa-exampleWLC01A) (config) #
DEBUG:netmiko:Pattern found: \(usa\-exampleWLC configure term

Enter Configuration commands, one per line. End with CNTL/Z

(usa-exampleWLC01A) (config) #
DEBUG:netmiko:write_channel: b'\n'
DEBUG:netmiko:Pattern is: \(usa\-exampleWLC
DEBUG:netmiko:_read_channel_expect read_data: 

(usa-exampleWLC01A) (config) #
DEBUG:netmiko:Pattern found: \(usa\-exampleWLC 

(usa-exampleWLC01A) (config) #
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:write_channel: b'mgmt-user admin root\n'
DEBUG:netmiko:read_channel: mgmt-user admin root

Password:
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:write_channel: b'examplepassword\n'
DEBUG:netmiko:read_channel: *********
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:write_channel: b'\n'
DEBUG:netmiko:Pattern is: \(usa\-exampleWLC
DEBUG:netmiko:_read_channel_expect read_data: *
DEBUG:paramiko.transport:EOF in transport thread
ktbyers commented 6 years ago

You could try this:

    SSH_Device = {
        'device_type': 'aruba_os',
        'ip': ipaddress,
        'username': u,
        'password': p,
        'secret': p,
        'default_enter': '\r\n'
    }

And see if that makes any difference.

MikeJurecki commented 6 years ago

That definitely made progress, It also fixed the saving issue that I was having. However, it now is saying the passwords dont match which is odd. It looks like the are exact in my log output but the log says differently. Any suggestions?

DEBUG:netmiko:read_channel: mgmt-user admin root

Password:
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:write_channel: b'exmpPass\r\n'
DEBUG:netmiko:read_channel: ********

Re-Type password:*
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:read_channel: 
DEBUG:netmiko:write_channel: b'exmpPass\r\n'
DEBUG:netmiko:read_channel: ********

Error: Passwords don't match Try again

(usa-exampleWLC01) (config) #

(usa-exampleWLC01) (config) #
ktbyers commented 6 years ago

How about setting the default_enter to just \r ?

MikeJurecki commented 6 years ago

I literally just tried that and it worked. That was the solution, it took the command. Thank you so much for all of the help. For the sake of people like me here is the complete working code below:

# INFO :  ArubaOS WLC Password Change Script
# INFO :  Created On: 7/26/2018
# INFO :  Description: Changes local admin password on ArubaOS Wireless Controllers

import netmiko
from datetime import datetime
from shutil import copy
import os
from os import listdir
from os.path import isfile, join
import logging
import time
import threading

run_date = datetime.today().date()
run_date = str(run_date)
run_time = datetime.now().time()
run_time = str(run_time)
run_time = run_time[:-7]
run_time = run_time.replace(':', '.')

logging.basicConfig(filename='Aruba_password_' + run_time + '.log', filemode='w', level=logging.DEBUG)

print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
print('ArubaOS Passoword Change SCRIPT')
print('Created on 7/26/2018')
print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
print('')

creds = []
with open('./creds/cred.txt', 'r') as file:
    creds = [line.strip() for line in file]

ios_ver = 'arubaos'
username = creds[0]
password = creds[1]

orig_path = './'
backup_path = './backups/'
postcap_path = './postcap/'
changes_path = './changes/'
logs_path = './logs/'

HOSTS = open('./hostlist/hostlist.txt', 'r')

HOST_FILE = []
for host1 in HOSTS:
    host1 = host1.rstrip('\n')
    if host1 == '':
        print('')  
    else:
        HOST_FILE.append(host1)

HOSTS.close()

failed_list = []

# INFO: This performed threading to hit multiple devices at a time

def thread_login(u, p):
    threads = []
    for ipaddress in HOST_FILE:
        t = threading.Thread(target=main_thread, args=(ipaddress, u, p,), )
        t.start()
        threads.append(t)
        print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
        print('STARTING NEW THREAD - IP ADDRESS:', ipaddress)
        print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
        time.sleep(4)

    for thread in threads:
        thread.join()

def main_thread(ipaddress, u, p): 

    current_time = datetime.now().time()
    current_time = str(current_time)
    print('Starting Change', ipaddress, current_time)

    SSH_Device = {
        'device_type': 'aruba_os',
        'ip': ipaddress,
        'username': u,
        'password': p,
        'secret': p,
        'default_enter': '\r'  # IMPORTANT: \r WAS THE KEY TO ALLOWING IT TO CHANGE THE PASSWORD
    }

    try:
        net_connect = netmiko.ConnectHandler(**SSH_Device)

    except Exception as e:
        e = str(e)
        failed = 'Connect Fail: ' + ipaddress + ':  ' + e
        failed_list.append(failed)
        print(e)

    try:
        # INFO: Creating Backup File
        print(ipaddress, str(datetime.now().time()), 'Gathering Backup Data')
        newconfigfilename = ipaddress + '_' + str(run_time) + '.cfg'
        newconfigfile = open(newconfigfilename, 'w')

        result1 = net_connect.send_command_expect('show run', delay_factor=2)
        newconfigfile.write(result1)

        newconfigfile.close()

    except Exception as e:
        e = str(e)
        failed = 'Connect Fail: ' + ipaddress + ':  ' + e
        failed_list.append(failed)
        print(ipaddress, str(datetime.now().time()), e)

    try:

        outputfilename = ipaddress + '_Change_' + run_date + run_time + '.txt'
        outputfile = open(outputfilename, 'w')

        outputfile.write('#### ' + ipaddress + ' ---- ' + run_time + '####\n')

        outputfile.write('###\n')
        outputfile.write('###\n')

        net_connect.config_mode()

        command = 'mgmt-user admin root'
        aruba_pass = 'exmpPass'

        configure4 = net_connect.send_command_timing(command)

        if 'Password:' in configure4:
            configure4 += net_connect.send_command_timing(aruba_pass)

        if 'Re-Type' in configure4:
            configure4 += net_connect.send_command_timing(aruba_pass)

        print('Password Configuration Applied', ipaddress)

        outputfile.write(configure4 + '\n')

        outputfile.write('###\n')
        outputfile.write('###\n')
        print('----')

        # INFO: Saving configuration
        outputfile.write('###\n')
        outputfile.write('###Saving Configuration\n')
        print(ipaddress, str(datetime.now().time()), 'Saving Configuration')

        net_connect.exit_config_mode()

        output2 = net_connect.save_config()
        outputfile.write(output2 + '\n')
        print(ipaddress, str(datetime.now().time()), output2)
        print('----')

        outputfile.close()

    except Exception as e:
        e = str(e)
        failed = 'Connect Fail: ' + ipaddress + ':  ' + e
        failed_list.append(failed)
        print(e)

# INFO: Threading Begins
thread_login(u=username, p=password)  

# INFO: This is moving all files to correct directory
filelist = [f for f in listdir(orig_path) if isfile(join(orig_path, f))]

# Moving Backup Files
for item in filelist:
    try:
        filename = orig_path + item

        if item.startswith("postcap"):
            copy(filename, postcap_path)
            os.remove(os.path.join(orig_path, item))

        if item.endswith(".cfg"):
            copy(filename, backup_path)
            os.remove(os.path.join(orig_path, item))

        if item.endswith(".txt"):
            copy(filename, changes_path)
            os.remove(os.path.join(orig_path, item))

        if item.endswith(".log"):
            copy(filename, logs_path)
            os.remove(os.path.join(orig_path, item))

    except:
        continue

# INFO: Creates failed file for all exceptions, with the IP Address
failedfile = 'FailedFile.txt'
failedfile2 = open(failedfile, 'w')
c = 1
for item in failed_list:
    failedfile2.write(str(c) + '. ' + item + '\n')
    c += 1

failedfile2.close()

# INFO: End of Script
end_time = datetime.now().time()
end_time = str(end_time)
end_time = end_time[:-7]
end_time = end_time.replace(':', '.')

print('Start Time:', run_time)
print('End time:', end_time)

@ktbyers Thanks again for all of the help!!! You are a great person!

ktbyers commented 6 years ago

I am re-opening as we should submit a PR on the Aruba driver to change this to be the default behavior.

sjtarik commented 5 years ago

@BigPat @ktbyers thanks for finding a soln to this.

xiaodonq commented 5 years ago

I got "TypeError: init() got an unexpected keyword argument 'default_enter'", any suggesting with this bug?

ktbyers commented 5 years ago

@xiaodonq Please create a separate issue and post your code and the exception stack.

xiaodonq commented 5 years ago

ktbyers@, i created https://github.com/ktbyers/netmiko/issues/1318, if you can support would be appreciate!