Skip to content

Commit 562afc5

Browse files
committed
Script to send email alert for interface flapping
1 parent ba8f024 commit 562afc5

File tree

1 file changed

+192
-0
lines changed

1 file changed

+192
-0
lines changed
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
#
2+
# Copyright (c) 2018 Krishna Kotha <krkotha@cisco.com>
3+
# All rights reserved.
4+
#
5+
# Redistribution and use in source and binary forms, with or without
6+
# modification, are permitted provided that the following conditions
7+
# are met:
8+
# 1. Redistributions of source code must retain the above copyright
9+
# notice, this list of conditions and the following disclaimer.
10+
# 2. Redistributions in binary form must reproduce the above copyright
11+
# notice, this list of conditions and the following disclaimer in the
12+
# documentation and/or other materials provided with the distribution.
13+
#
14+
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17+
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20+
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21+
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22+
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23+
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24+
# SUCH DAMAGE.
25+
#
26+
# PURPOSE of this SCRIPT
27+
# The purpose of this script is if a interface flapped 5 times in last 5 minutes it will shutdown that interface. You can change that flapping count to what ever you want.
28+
# Then it will wait for 5 mins and enable that interface.
29+
# If still flapping atleast once it will shutdown that interface and will send an email alert.
30+
#
31+
#
32+
# This script monitors the interface GigabitEthernet1/0/5, change the interface ID based on your requirement.
33+
#
34+
#
35+
# This script requires the following variables to be defined:
36+
# FROM_ADDR
37+
# TO_ADDR
38+
# name-server ip address
39+
# http_proxy and https_proxy commands
40+
#
41+
42+
# importing necessary modules
43+
import os
44+
import sys
45+
import cli
46+
import time
47+
import difflib
48+
from datetime import datetime
49+
from time import strptime
50+
from time import mktime
51+
import smtplib
52+
import shutil
53+
from email.MIMEMultipart import MIMEMultipart
54+
from email.MIMEText import MIMEText
55+
import subprocess
56+
57+
58+
def checkPortFlap(port_flaps_cnt,interface):
59+
60+
# calculate current time using time module
61+
currTime = time.time()
62+
print("curr time is: %s" % (currTime))
63+
64+
# retrieve the show log output
65+
arr_output = cli.cli("show log").split("\n")
66+
67+
for line in arr_output:
68+
69+
# In this example I am monitoring the Gi 1/0/5 interface, based on your requirement change the interface ID.
70+
if(line.find("GigabitEthernet1/0/5, changed state to down") != -1):
71+
print("The line %s indicates a port flap action" % (line))
72+
line_arr = line.split("%")
73+
74+
# seperate the date from the log lines and convert the matching line to list objects and strings
75+
date_in_log = line_arr[0]
76+
print("the entry date is: %s" % (date_in_log))
77+
line_arr = line.split(",")
78+
line_arr_1 = line_arr[0].split(" ")
79+
str_line_arr_0=''.join(line_arr_1[0])
80+
81+
# remove * and : from the strings
82+
str_line_arr_0= str_line_arr_0[1:]
83+
str_line_arr_1=''.join(line_arr_1[3])
84+
str_line_arr_1=str_line_arr_1[:-1]
85+
86+
# parse a string to represent a time according to a format
87+
log_time = time.strptime(str_line_arr_0+" "+line_arr_1[1]+" "+line_arr_1[2]+" "+str_line_arr_1, "%b %d %Y %H:%M:%S")
88+
89+
# calculate the log time in seconds
90+
log_time_secs = mktime(log_time)
91+
92+
# calculate the difference from current time to log time
93+
delta=currTime-log_time_secs
94+
interface = line_arr_1[len(line_arr_1) - 1]
95+
print("the interface is: %s" % (interface))
96+
97+
# if delta is less than 5 minutes that log will be counted.
98+
if delta <= 300:
99+
port_flaps_cnt = port_flaps_cnt + 1
100+
return port_flaps_cnt, interface
101+
102+
103+
104+
def send_e_mail(subject):
105+
"""
106+
send an e mail from the Cisco network to anyone -
107+
Note: This example uses from address as a Cisco server, Change the domain to your SMTP server to send email from your domain.
108+
"""
109+
110+
# retrieve the hostname using in-built cli module
111+
host_name = cli.cli("show running-config | include hostname")
112+
FROM_ADDR = 'xxxx@cisco.com'
113+
TO_ADDR = 'xxxx@gmail.com'
114+
115+
# create the message
116+
msg = MIMEMultipart()
117+
msg['From'] = FROM_ADDR
118+
msg['To'] = TO_ADDR
119+
msg['Subject'] = "%s - %s" % (subject, host_name)
120+
text = "This is an automated e mail message:\n===========================\nAn on-Box Python script running on a Cisco Polaris guestshell device and detected that the %s %s \n===========================\n\n\n===========================\n\n" % (subject, host_name)
121+
msg.attach(MIMEText(text, 'plain'))
122+
123+
# connect to server and send
124+
server = smtplib.SMTP('outbound.your_company_name.com', 25)
125+
server.sendmail(FROM_ADDR, TO_ADDR, msg.as_string())
126+
server.quit()
127+
128+
129+
def set_device_to_role_as_cisco_mail_server():
130+
"""
131+
Manipulates the /etc/resolv.conf and set it to a Cisco mail server. The commands are known to the average network Linux admin...
132+
"""
133+
commands_to_run_on_gs = [
134+
"sudo rm /etc/resolv.conf",
135+
"sudo touch /etc/resolv.conf",
136+
"echo \"nameserver x.x.x.x\" | sudo tee -a /etc/resolv.conf",
137+
"echo \"domain x.x.x.x.com\" | sudo tee -a /etc/resolv.conf",
138+
"echo \"export http_proxy=http://x.x.x.x:80/\" | sudo tee -a /etc/bashrc",
139+
"echo \"export https_proxy=http://x.x.x.x:80/\" | sudo tee -a /etc/bashrc",
140+
"echo \"export ftp_proxy=http://x.x.x.x:80/\" | sudo tee -a /etc/bashrc",
141+
"echo \"export no_proxy=.x.x.x.x.com\" | sudo tee -a /etc/bashrc",
142+
"echo \"export HTTP_PROXY=http://x.x.x.x:80/\" | sudo tee -a /etc/bashrc",
143+
"echo \"export HTTPS_PROXY=http://x.x.x.x:80/\" | sudo tee -a /etc/bashrc",
144+
"echo \"export FTP_PROXY=http://x.x.x.x:80/\" | sudo tee -a /etc/bashrc"
145+
]
146+
for command in commands_to_run_on_gs:
147+
p = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
148+
(output, err) = p.communicate()
149+
print "Linux command output is", output
150+
151+
152+
# main code:
153+
if __name__ == '__main__':
154+
155+
# these commands are need to remove msec and add year in the show log command
156+
cli.configurep("service timestamps log datetime")
157+
cli.configurep("service timestamps log datetime year")
158+
159+
160+
port_flaps_cnt = 0
161+
interface = None
162+
port_flaps = checkPortFlap(port_flaps_cnt,interface)
163+
164+
if(port_flaps[0] == 10):
165+
if(port_flaps[1] is not None):
166+
print("shutting down interface %s" % (port_flaps[1]))
167+
168+
# shut down the interface using cli module
169+
#cli(["interface %s" % (port_flaps[1]), "shut", "end"])
170+
cli.configurep(["interface %s" % (port_flaps[1]), "shut", "end"])
171+
172+
# wait for 5 mins to monitor the interface flap again
173+
time.sleep(300)
174+
print("Waited for 5 mins Enabling the interface %s" % (port_flaps[1]))
175+
176+
# enable the interface
177+
#cli("cont f", "interfact %s" % (port_flaps[1]), "no shut", "end")
178+
cli.configurep(["interface %s" % (port_flaps[1]), "no shut", "end"])
179+
port_flaps_cnt = 0
180+
interface = None
181+
182+
# re check the interface is flapping or not
183+
port_flaps = checkPortFlap(port_flaps_cnt,interface)
184+
185+
# if still flapping shut down the interface and send email
186+
if(port_flaps[0] >= 2):
187+
if(port_flaps[1] is not None):
188+
print("shutting down interface %s" % (port_flaps[1]))
189+
#cli("cont f", "interfact %s" % (port_flaps[1]), "shut", "end")
190+
cli.configurep(["interface %s" % (port_flaps[1]), "shut", "end"])
191+
set_device_to_role_as_cisco_mail_server()
192+
send_e_mail("interface %s is flapping and did admin shutdown" % (port_flaps[1]))

0 commit comments

Comments
 (0)