Closed bill831231 closed 5 years ago
@bill831231 Are you using a device_type=cisco_nxos
.
Also a better pattern for handling commands with additional prompting is to do something like the following (using the send_command_timing() method).
cmd1 = "copy running-config tftp:"
result = net_connect.send_command_timing(cmd1)
if 'Address or name of remote host' in result:
result += net_connect.send_command_timing(Tftp_server)
if 'Destination filename' in result:
# switch back to send_command() here as this might be slow
result += net_connect.send_command()
@ktbyers ,
Hi Kirk,
Thanks a lot for the feedback, I have repeat the test, here are some more details:
I have just tried your new commands, it works, and I have tried my code again with multi-thread and without multi-thread.
in the single Thread mode, the way with one all command in one line also works
command_ConfSave="copy running-config tftp:\n\r\n%s\n\r" % Tftp_server
result=net_connect.send_command_expect(command_ConfSave)
in the multi-thread mode, both of the following methods got the same error:
method 1:
command_ConfSave="copy running-config tftp:\n\r\n%s\n\r" % Tftp_server
result=net_connect.send_command_expect(command_ConfSave)
method 2:
cmd1 = "copy running-config tftp:"
result = net_connect.send_command_timing(cmd1)
if 'Address or name of remote host' in result:
result += net_connect.send_command_timing(Tftp_server)
if 'Destination filename' in result:
result += net_connect.send_command()
Do you have some suggestion for running in multi-thread or multi-process?
My multi-thread code, may be there are some error. and the behavior is different from Catalyst and Nexus
class CommWithDevice(object):
def __init__(self):
self.tftp="10.139.27.38"
def NBuildUp(self,line):
LoginInfo=line.split(",")
CiscoLogin={}
if int(LoginInfo[-1])==0:
CiscoLogin['device_type']=LoginInfo[0]
CiscoLogin['ip']=LoginInfo[1]
CiscoLogin['username']=LoginInfo[2]
CiscoLogin['password']=LoginInfo[3]
CiscoLogin['secret']=LoginInfo[4]
CiscoLogin['verbose']=LoginInfo[5]
return CiscoLogin
def ShowVersion(self):
net_connect = ConnectHandler(**self.CiscoIOS)
net_connect.enable()
command_ConfSave="show version"
result=net_connect.send_command_expect(command_ConfSave)
print (result)
net_connect.disconnect()
def BBakC(self,q):
line=q.get()
LoginInfo=self.NBuildUp(line)
net_connect = ConnectHandler(**LoginInfo)
net_connect.enable()
Tftp_server=self.tftp
command_ConfSave="copy running-config tftp:\n %s\n\r" % Tftp_server
result=net_connect.send_command_expect(command_ConfSave)
print (result)
if '%' in result:
with open('hostbakerr.txt','at') as f:
for ii in result:
f.write(ii)
net_connect.disconnect()
q.task_done()
def BBakCt(self,q):
line=q.get()
LoginInfo=line.split(",")
CiscoLogin={}
if int(LoginInfo[-1])==0:
CiscoLogin['device_type']=LoginInfo[0]
CiscoLogin['ip']=LoginInfo[1]
CiscoLogin['username']=LoginInfo[2]
CiscoLogin['password']=LoginInfo[3]
CiscoLogin['secret']=LoginInfo[4]
CiscoLogin['verbose']=LoginInfo[5]
net_connect = ConnectHandler(**CiscoLogin)
net_connect.enable()
Tftp_server=self.tftp
command_ConfSave="copy running-config tftp:\n %s\n\r" % Tftp_server
result=net_connect.send_command_expect(command_ConfSave)
print (result)
if '%' in result:
with open('hostbakerr.txt','at') as f:
for ii in result:
f.write(ii)
net_connect.disconnect()
q.task_done()
def BBakN(self,q):
line=q.get()
LoginInfo=self.NBuildUp(line)
net_connect = ConnectHandler(**LoginInfo)
net_connect.enable()
Tftp_server=self.tftp
cmd1 = "copy running-config tftp:"
result = net_connect.send_command_timing(cmd1)
if 'Address or name of remote host' in result:
result += net_connect.send_command_timing(Tftp_server)
print(result)
if 'Destination filename' in result:
# switch back to send_command() here as this might be slow
result += net_connect.send_command_timing('\n')
print(result)
print (result)
net_connect.disconnect()
q.task_done()
def ABC(self, file):
q=Queue()
MaxThreadNo=150
tstart=time.time()
for i in range(MaxThreadNo):
t=threading.Thread(target=self.BBakCt,args=(q,))
t.setDaemon(True)
t.start()
with open(file,'r') as testlist:
for line in testlist:
q.put(line)
q.join()
tend=time.time()
print("finished, totally takes %s s" %(tend-tstart) )
def ABN(self, file):
q=Queue()
MaxThreadNo=50
tstart=time.time()
for i in range(MaxThreadNo):
t=threading.Thread(target=self.BBakN,args=(q,))
t.setDaemon(True)
t.start()
with open(file,'r') as testlist:
for line in testlist:
q.put(line)
q.join()
tend=time.time()
print("finished, totally takes %s s" %(tend-tstart) )
if name=="main":
LoginInstance= CommWithDevice()
LoginInstance.ABC('DeviceInfo.txt')
LoginInstance.ABC('Ntest.txt')
@bill831231 What are you trying to do at a high-level? Is it just backup configurations? If so, don't use TFTP just use straight SSH to do this.
Hi Kirk,
Thanks for the reply, backup configuration is the first function need this kind of interactive method :), then I found it is very hard to do the trouble shooting, since the output cannot be obtained with some easy way. I have tried to give the parameter for pattern search, seems also easy to write something with interaction, any suggestion for it?
thanks again, and nice evening
Mit freundlichen Grüßen Wu,Peng
2017-08-01 19:50 GMT+02:00 Kirk Byers notifications@github.com:
@bill831231 https://github.com/bill831231 What are you trying to do at a high-level? Is it just backup configurations? If so, don't use TFTP just use straight SSH to do this.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/ktbyers/netmiko/issues/528#issuecomment-319445875, or mute the thread https://github.com/notifications/unsubscribe-auth/AUXaqJj4ccDWeqog16fbkzrDshjreuKwks5sT2VjgaJpZM4OeQ5E .
@bill831231 So if single thread, you should be able to just do this (as you referenced above):
cmd1 = "copy running-config tftp:"
result = net_connect.send_command_timing(cmd1)
if 'Address or name of remote host' in result:
result += net_connect.send_command_timing(Tftp_server)
if 'Destination filename' in result:
# switch back to send_command() here as this might be slow
result += net_connect.send_command()
Not sure I understand your difficulty getting output statement? Are you talking in a multi-process/multi-thread context?
If running multithreads/multiprocess I would just make a function out of my backup process (note, I wouldn't use TFTP; I would do the backup straight using SSH i.e. just grab 'show run' from the SSH channel).
Here is an example using a queue. Threading code would be almost identical.
https://github.com/ktbyers/pynet-ons-jul17/blob/master/threads_procs/proc_w_queue.py
Note, you can get into a deadlock situation if you try to pass too much data through a queue.
Hi Kirk,
Seems I have a special case, I have test the code for nexus with single thread. it is working with the interaction way (send something, check the result, then send something). then just change to a multi-thread way, it is not working, then I want to check out what exactly is the going wrong(ssh link, input, output or some other things), then faced some difficulties there. and strange thing is change the code for from single thread to multi thread, seems no impact for catalyst at all :) Now trying to separate the code for nexus out from the calalyst.
thanks a lot for your support have a nice day
Mit freundlichen Grüßen Wu,Peng
2017-08-02 19:17 GMT+02:00 Kirk Byers notifications@github.com:
@bill831231 https://github.com/bill831231 So if single thread, you should be able to just do this (as you referenced above):
cmd1 = "copy running-config tftp:" result = net_connect.send_command_timing(cmd1) if 'Address or name of remote host' in result: result += net_connect.send_command_timing(Tftp_server) if 'Destination filename' in result:
switch back to send_command() here as this might be slow
result += net_connect.send_command()
Not sure I understand your difficulty getting output statement? Are you talking in a multi-process/multi-thread context?
If running multithreads/multiprocess I would just make a function out of my backup process (note, I wouldn't use TFTP; I would do the backup straight using SSH i.e. just grab 'show run' from the SSH channel).
Here is an example using a queue. Threading code would be almost identical.
https://github.com/ktbyers/pynet-ons-jul17/blob/master/ threads_procs/proc_w_queue.py
Note, you can get into a deadlock situation if you try to pass too much data through a queue.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/ktbyers/netmiko/issues/528#issuecomment-319738849, or mute the thread https://github.com/notifications/unsubscribe-auth/AUXaqKXhoKTFsvy85jf9AinaMl7z6ftiks5sUK8fgaJpZM4OeQ5E .
@ktbyers Hi Kirk,
I am trying to use multiprocess and ftp to copy ios image from ftp server. I tried send_command and send_command_timing, but received the following error: IOError: Search pattern never detected in send_command_expect: Accessing\ ftp\:\/\/*****\:*****\@...\/example-img-file.bin...
Upon looking at the source code, I observed that the send_command method looks for the device hostname prompt, but it is failing as it is timing out with the predefined delay factor and max loops. Is there a way to change these predefined values? Also can I change the method to look for a different prompt?
Thanks in advance! Appreciate your awesome work!
@bosspuj Can you post your code?
@ktbyers
#!/usr/bin/env python
from __future__ import absolute_import, division
from tabulate import tabulate
from pprint import pprint as pp
from progressbar import ProgressBar
from datetime import date
from mytools import get_credentials
import netmiko
import json
import re
import signal
import sys
import os
import difflib
import multiprocessing as mp
import time
signal.signal(signal.SIGPIPE, signal.SIG_DFL) # IOError: Broken pipe
signal.signal(signal.SIGINT, signal.SIG_DFL) # KeyboardInterrupt: Ctrl-C
netmiko_exceptions = (netmiko.ssh_exception.NetMikoTimeoutException,
netmiko.ssh_exception.NetMikoAuthenticationException)
username, password = get_credentials()
scriptdir = os.path.dirname(os.path.realpath('__file__'))
ips_file = os.path.join(scriptdir, 'hosts/tst_swdist_ips.txt')
with open(ips_file) as in_file:
ips = in_file.read().splitlines()
def connect_device(device_ip):
connect = netmiko.ConnectHandler(ip = device_ip, device_type = 'cisco_ios', username = username, password = password)
return connect
def copy_sw(ip):
connection = connect_device(ip)
print('\n')
print('*'*79)
ngear = connection.base_prompt
print('Connecting to Device %s - %s' %(ngear, ip))
version = connection.send_command('show version')
ver = re.search('(\/(.*)\/)*\w{1,}([.-]\w{1,})+\.bin', version)
run_img = ver.group(2)
if run_img is None:
run_img = ver.group(0)
else:
pass
print('~'*60)
print('\nRunning Image Version: ')
print(run_img)
dir = connection.send_command('dir | exclude .lic|.pcap|.pkg|.cfg|.tar|.dat|.shtml|.cis|EST')
directory = re.search('(\w{5,9})\:\/', dir)
directory = directory.group(1)
img_repository = []
for d in os.listdir('/home/netftp'):
img_repository.append(d)
print('~'*60)
print('\nAvailable Images in Repository...')
for d in img_repository:
print(d)
suitable_img_files = difflib.get_close_matches(run_img, img_repository, 1)
suitable_img_file = suitable_img_files[0]
print('~'*60)
print('\nBest Match:')
print(suitable_img_file)
print('\nFile copy in progress...\n')
print('copy ftp://username:pass@internal_ip/%s %s:/...'%(suitable_img_file, directory))
connection.send_command_timing('copy ftp://username:pass@internal_ip/%s %s:/'%(suitable_img_file, directory))
connection.send_command_timing('\n')
time.sleep(300)
connection.disconnect()
def mp_handler():
p = mp.Pool(5)
p.map(copy_sw, ips)
try:
mp_handler()
except netmiko_exceptions as e:
print('Failed to ', ip, e)
except AttributeError as e:
print('Failed to ', ip, e)
I am looking for a way to avoid that time.sleep(300)... make it dynamic (based on file copy time), instead of a static predefined value....
Thanks.
Probably try:
connection.send_command('copy ftp://username:pass@internal_ip/%s %s:/'%(suitable_img_file, directory), delay_factor=4)
Note, by default send_command
will wait 100 seconds, so delay_factor=4 will wait 400 seconds. If you need longer than this, you can increase it to a bigger value.
@ktbyers Thanks for the help! Much appreciated!
Dear all,
I used the following lines to backup a configuration from cisco sw to a tftp server
it works with Catalyst switch, but when with Nexus, always facing an error as following Exception in thread Thread-2:
seems the interaction between the netmiko and switch had an error, can not "#" from switch
Catalyst version 15.0(1)SE3 Nexus version 6.0(2)N2(2) Netmiko 1.4.1
My question: is there some way can help to see the realtime output from this ssh session? it may help to do some more trouble shooting on it
thanks a lot