If you are a cisco employee, u can test the code using ASR9K devices in lab. I did test on 172.18.87.36 (be connected to cisco vpn).
The use case of the code is that, customer has to everytime manually upload logs and files in SR which are shared by TAC or other teams. Using this code, the hostname, sr_number & commands are given as input, and the output in .txt file is automatically uploaded in SR. And the show tech files are uploaded to the FTP server of your choice. The programming language used is Python.
# -*- coding: utf-8 -*-
"""
Created on Thu Apr 18 13:02:17 2019
@author: rdhavade
The intent of the script is to take input as hostnames, commands and sr_number.
And the output generated from router will be automatically uploaded to SR.
Input are three .txt files in same folder as .py file:
hostnames.txt, commands.txt.txt & sr_number.txt.
Output: text file Logs uploaded to SR. And show tech will be uploaded to ftp.
I have used ftp server IP as per my lab setup.
"""
import paramiko
import time
import os
import sys
import datetime
import re
command_list = []
hostname_list = []
final_result = []
datetime_object = datetime.datetime.now()
str_date_obj = str(datetime_object).replace(' ','_')
str_date_obj_1 = str_date_obj.replace(':','.')
sr_num = open("sr_number.txt","r")
# file sr_number.txt should contain only one SR number
for line in sr_num:
sr_number = line
in_file = open("commands.txt.txt","r")
# file commands.txt.txt should contains multiple commands, one on one line
for line in in_file:
command_list.append(line)
in_file.close()
out_file_name = "SR_" + str(sr_number).strip() + "_" + str_date_obj_1 + "_logs.txt"
out_file = open(out_file_name,"w")
host_file = open('hostnames.txt','r')
for hostname in host_file:
hostname_list.append(hostname)
script_debug_logs = str(sr_number).strip() + '_' + str_date_obj_1 + '_debug.txt'
debug_logs_fh = open(script_debug_logs,'w')
num_of_cmds = len(command_list)
num_of_hostname = len(hostname_list)
final_output = []
c1 = paramiko.SSHClient()
c1.load_system_host_keys()
c1.get_host_keys()
c1.set_missing_host_key_policy(paramiko.AutoAddPolicy())
for j in range (0,len(hostname_list)):
c1.connect(hostname_list[j].strip(), port=22, username="cisco_cco_username", password = "password")
channel = c1.invoke_shell()
print('Login to hostname ' + str(hostname_list[j]) + ' successful!.')
debug_logs_fh.write('Login to hostname ' + str(hostname_list[j]) + ' successful!.')
time.sleep(3)
channel.send('terminal length 0\n')
time.sleep(2)
out = channel.recv(1000)
out_file.write(out.decode("ascii"))
final_result.append(out.decode('ascii'))
len_fr = len(final_result)
# get hostname
channel.send('show run hostname\n')
time.sleep(5)
while True:
if channel.recv_ready() == True:
out = channel.recv(1000)
break
decoded_out = out.decode('ascii')
word = ''
list_out = []
for char in decoded_out:
if char == ' ':
list_out.append(word)
word = ''
if char != ' ':
word = word + char
list_out.append(word)
try:
str_list_out_index_hn = str(list_out[len(list_out)-2]).index('hostname')
except:
print ('Cannot get hostname. Some error has ocurred. Please retry!!! If error re-occurs contact developer')
channel.close()
c1.close()
out_file.close()
debug_logs_fh.close()
raise ValueError
hostname_final_list = list_out[len(list_out)-1]
hostname_final = hostname_final_list.split('\r')[0]
hostname_final = hostname_final + "#"
print('Got hostname as ' + str(hostname_final))
time.sleep(5)
print('Command Execution in progress')
for i in range (0,len(command_list)):
print('In for loop for value of i ' + str(i))
debug_logs_fh.write('In for loop for value of i ' + str(i))
while channel.send_ready():
print('in 1st while loop')
debug_logs_fh.write('in 1st while loop')
time.sleep(1)
channel.send(command_list[i])
time.sleep(5)
break
while True:
while channel.recv_ready():
print('value of recv_ready in 2nd while loop is \n' +
str(channel.recv_ready()) + ' for command \n' + str(command_list[i]))
debug_logs_fh.write(('value of recv_ready in 2nd while loop is \n' +
str(channel.recv_ready()) + ' for command \n' + str(command_list[i])))
print('in 2nd while loop')
debug_logs_fh.write('in 2nd while loop')
out = channel.recv(9999)
#print('value of out in 2nd while loop is \n' + str(out.decode('ascii')))
out_file.write(out.decode("ascii"))
final_result.append(out.decode('ascii'))
len_fr = len(final_result)
print('value of recv_ready after 2nd while loop is ' + str(channel.recv_ready()))
debug_logs_fh.write('value of recv_ready after 2nd while loop is ' + str(channel.recv_ready()))
if str(final_result[len_fr-1]).endswith(hostname_final):
break
else:
continue
print('\nexecution of for loop for i = ' + str(i) + ' completed.\n')
time.sleep(3)
#### CHECKING show-tech files and uploading to ftp
# get number of files to be uploaded
final_list_enum = [i for i, item in enumerate(final_result) if re.search('.*Show tech output.*',item)]
# final_list_enum contains index of final_result where filename is present
files_saved = []
for index in final_list_enum:
files_saved.append(final_result[index])
for i in range (0,len(files_saved)):
print('Saving file to ftp for location ' + files_saved[i])
debug_logs_fh.write('Saving file to ftp for location ' + files_saved[i])
loc = files_saved[i].split('CPU0')[2].replace('\r','').replace('\n','').lstrip('//')
while channel.send_ready():
time.sleep(1)
# change ftp command as per need
print('sending copy command')
channel.send('copy ' + loc + ' ' + 'ftp://admin:admin123@10.65.63.234/ vrf calo-mgmt' + '\n' + '\n')
# AFTER SENDING ABOVE COMMAND NEED TO TAKE ACTION BASED ON PROMPT GENERATED BY ROUTER.
# WHETHER IT ASKS FOR 'Address or name of remote host[]?' or destination file name etc.
# AS PER YOUR ROUTER'S PROMPT AFTER FTP COMMAND, NEED TO AMEND CODE FURTHER.
time.sleep(5)
break
while True:
while channel.recv_ready():
print('In While loop uploading tech file')
out = channel.recv(9999)
out_file.write(out.decode("ascii"))
final_result.append(out.decode('ascii'))
len_fr = len(final_result)
if str(final_result[len_fr-1]).endswith(hostname_final):
break
else:
print('This is else in uploading file section')
continue
##########################################################
print('Command Execution complete, closing channel.')
print('status of recv_ready ' + str(channel.recv_ready())) # should be false
try:
bool_final_status = channel.recv_ready()
if bool_final_status == True:
raise ValueError('Some Data has been lost, please retry !!!')
except ValueError as ve:
print(ve)
finally:
channel.close()
c1.close()
out_file.close()
debug_logs_fh.close()
import email_send_attachment
sender = email_send_attachment.email_attach.send_email(subject_given = ('SR:' + str(sr_number)),
body = ('Logs attaching in SR :' + str(sr_number)),
filename = out_file_name)
print('finished execution, logs will be uploaded to SR.')
# -*- coding: utf-8 -*-
"""
Created on Thu Apr 18 22:11:39 2019
@author: rdhavade
"""
# install keyring and yagmail python package
# in the yagmail package under password.py importing keyring was missed, added it.
import yagmail
class email_attach(object):
def send_email(subject_given,body,filename):
#receiver = "pythontester121@gmail.com"
body = "Hi, Attaching logs in case number "
yagmail.register('pythontester121@gmail.com','bhaikaun123')
yag = yagmail.SMTP("pythontester121@gmail.com")
yag.send(
to='rdhavade@cisco.com',
subject= subject_given,
contents=body,
attachments=filename,
)
if __name__ == "__main__":
email_attach.send_email('tseter subject case number','tester body','output.txt')
I hope this helps someone looking for near around requirement.
Also, post your suggestions on any optimizations that can be done further.