cancel
Showing results for 
Search instead for 
Did you mean: 
cancel

Automatically collect logs and upload .txt to SR, and show techs to FTP server.

315
Views
15
Helpful
6
Comments
Cisco Employee

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.

 

 

 

6 Comments
Cisco Employee

Looks Good Rohit ! 

Facing this issue with multiple customers where they need to collect a set of logs requested by TAC/Engineering, and they miss out some of them or are unable to collect correctly.

 

Hope this script helps such cases. 

Cisco Employee

Please add procedure how we can install this in customer server and then a sample run example for reference.

Cisco Employee
Brilliant code Rohit... hope this is tested.
Cisco Employee

Yea Apoorva you are right, hopefully very soon we are going to make it live in Reliance JIO. And later can be adopted as a standard.
I have tested the code, will post a WebEx recording of it to give better clarity on it's usage procedure.

Cisco Employee
@supriya Tatini (btatini), Yes I have tested it with multiple flavours and multiple enhancements have been done over it. Now, the code is in a very good shape that even a very big output doesn't miss any characters. Earlier it did happen that small outputs were working good, but data-loss was observed with bigger outputs. Now, this challenge has been taken care of and we are on the final stages.
Cisco Employee

For a demo on the usage checkout link-

https://cisco.webex.com/cisco/lsr.php?RCID=10a3835522514f98a12dc3fbe2d4a08a

 

Password: CqV7fwA2

Content for Community-Ad
June's Community Spotlight Awards