Configuring Cisco Embedded Event Manager (EEM) - Programming IOS
In today's network; everyone tries to automate as much as possible. I will cover one such topic today - EEM (Embedded Event Manager) in Cisco devices. EEM is supported by Cisco IOS, XR and NX-OS.
EEM allows automation for Cisco device administrators by tracking and monitoring events in network devices and take actions when those events occur. For example; we want to shutdown an network interface at a scheduled time, change interface description when new LLDP neighbors are detected, backup device configuration etc.
Overview of EEM (Embedded Event Manager)
EEM - we need to understand two topics:
- EEM event detectors - We use event detector to subscribe to an event; for example - interface went down, routing neighbor is lost etc. When such an event is occurred; we will do some automated actions.
- EEM actions - When an EEM event occurs; we will do some predefined tasks automatically; these are called EEM actions. For example; send an email alert when an interface down event is detected.
Below picture from Cisco© explains the concept of EEM in a easy way -
We can configure EEM in two ways -
- Applet - Most easiest way. This method will be used mostly in this blog.
- TCL scripts - Complex and we get the full power of Cisco's implementation of TCL programming language.
Basic EEM Configuration
Let's start with a basic example - We want to generate an arbitrary syslog message. We will configure following in our switch -
event manager applet Applet_Syslog
!!! We are not subscribing to any event; we will run manually the applet
event none
!!! Adding comment for our action
action 1.0 comment "Generate a syslog message with EEM applet"
!!! Take an EEM action by generating a syslog message
action 1.1 syslog msg "Welcome to EEM with Applet!!!"
Now we will run the applet manually by using command below and see a syslog message has been generated.
SW01# event manager run Applet_Syslog
SW01#
*Jul 5 09:27:37.505: %HA_EM-6-LOG: Applet_Syslog: Welcome to EEM with Applet!!!
Now we will convert our applet to a TCL script to show how to use TCL scripts with EEM.
Let's create a TCL script file in the flash -
SW01#tclsh
SW01(tcl)#puts [open "flash:Eem_Syslog.tcl" w+] {
+>::cisco::eem::event_register_none
+>
+>namespace import ::cisco::eem::*
+>namespace import ::cisco::lib::*
+>
+>array set arr_einfo [event_reqinfo]
+>
+># "Generate a syslog message with EEM applet"
+>action_syslog msg "Welcome to EEM with TCL script!!!"
+>}
SW01(tcl)#tclquit
Now have a look at the file in IOS -
SW01#more Eem_Syslog.tcl
!!! We are not subscribing to any event; we will run manually the applet
::cisco::eem::event_register_none
!!! Importing necessary EEM libraries
namespace import ::cisco::eem::*
namespace import ::cisco::lib::*
array set arr_einfo [event_reqinfo]
# "Generate a syslog message with EEM applet"
action_syslog msg "Welcome to EEM with TCL script!!!"
After that we need to register both the directory where our TCl script is saved and the script itself.
!!! Register the directory where the script resides
SW01(config)#event manager directory user policy flash0:/
!!! Register the script
SW01(config)#event manager policy Eem_Syslog.tcl
After that we can run the script same way as the applet.
SW01#event manager run Eem_Syslog.tcl
SW01#
*Jul 5 14:44:24.920: %HA_EM-6-LOG: Eem_Syslog.tcl: Welcome to EEM with TCL script!!!
Advanced EEM Configuration
Now we will do two examples of EEM which are event driven.
Example 1 - shutdown interface at a specific time
We will shutdown an interface (gi0/1) at a scheduled time (at 20:00 everyday). And we will turn it back on gi0/1 at 07:00 everyday. Let's create our applet -
event manager applet Applet_Shutdown_Gi0/1
!!! An event will occur with cron at 20:00 everyday
event timer cron cron-entry "0 20 * * *"
action 1.0 comment "Shutdown Gi0/1 port at 20:00 everyday"
!!! We will run below commands/actions to shutdown the interface
action 1.1 cli command "enable"
action 1.2 cli command "configure terminal"
action 1.3 cli command "interface Gi0/1"
action 1.4 cli command "shutdown"
action 1.5 cli command "end"
action 1.6 syslog msg "Interface Gi1/0/1 has been shutdown with scheduled applet"
event manager applet Applet_Open_Gi0/1
!!! An event will occur with cron at 07:00 everyday
event timer cron cron-entry "0 7 * * *"
action 1.0 comment "Open Gi0/1 port at 07:00 everyday"
!!! We will run below commands/actions to turn on the interface
action 1.1 cli command "enable"
action 1.2 cli command "configure terminal"
action 1.3 cli command "interface Gi0/1"
action 1.4 cli command "no shutdown"
action 1.5 cli command "end"
action 1.6 syslog msg "Interface Gi1/0/1 has been opened with scheduled applet"
We will see the below message in logs when it is 20:00 o'clock.
SW01#
Jul 5 20:00:00.287: %HA_EM-6-LOG: Applet_Shutdown_Gi0/1: Interface Gi1/0/1 has been shutdown with scheduled applet
Example 2 - Change interface description from LLDP neighborship
We want to change our interface description when a LADP neighbor is added or deleted. Our interface description will be in the format - (LLDP-Neighbor-Name)-(LLDP-Neighbor-Port-Id) - SW02-Gi0/1. Now time to write our applet - one for adding interface description whenever a new LLDP neighbor is discovered for an interface and one for removing interface description when a LLDP neighbor is deleted for an interface.
event manager applet Applet_LLDP_Port_Description_Add
description "Automatically add interface description using LLDP neighbor information"
!!! Monitor lldp add events and match interface name that contains GigabitEthernet
event neighbor-discovery interface regexp GigabitEthernet.* lldp add
action 1.0 comment "Triming domain name from LLDP system name"
!!!We will exclude the domain name part from LLDP neighbor using regular expression
action 1.1 regexp "(^[^.]*)|(^[^.]*$)" "$_nd_lldp_system_name" match neighbor_host_name
action 2.0 comment "Update interface description and save the configuration"
action 2.1 cli command "enable"
action 2.2 cli command "configure terminal"
action 2.3 cli command "interface $_nd_local_intf_name"
action 2.4 cli command "description $neighbor_host_name-$_nd_port_id"
action 2.5 cli command "end"
action 2.6 cli command "write memory"
action 2.7 syslog msg "EEM applet added interface description for - $_nd_local_intf_name"
action 2.8 exit 0
event manager applet Applet_LLDP_Port_Description_Remove
description "Automatically delete interface description using LLDP neighbor information"
!!! Monitor lldp delete events and match interface name that contains GigabitEthernet
event neighbor-discovery interface regexp GigabitEthernet.* lldp delete
action 1.0 comment "Remove interface description and save the configuration"
action 1.1 cli command "enable"
action 1.2 cli command "configure terminal"
action 1.3 cli command "interface $_nd_local_intf_name"
action 1.4 cli command "no description"
action 1.5 cli command "end"
action 1.6 cli command "write memory"
action 1.7 syslog msg "EEM script deleted interface description for - $_nd_local_intf_name"
action 1.8 exit 0
Now some explanation about - $_nd_local_intf_name, $_nd_port_id. What are these and how can we know about them. These are built-in variables provided by different EEM events. We can get a the complete list of these variables for neighbor-discovery (both LLDP and CDP) by using the command below -
SW01#show event manager detector neighbor-discovery detailed (output truncated)
No. Name Version Node Type
1 neighbor-discovery 01.00 node0/0 RP
Tcl Configuration Syntax:
::cisco::eem::event_register_neighbor_discovery
[tag <tag-val>]
interface <interface-pattern>
[cdp {add | update | delete | all}]
[lldp {add | update | delete | all}]
LLDP EVENT VARIABLES:
protocol
lldp_system_name
lldp_system_description
lldp_port_description
COMMON VARIABLES:
$_nd_notification
$_nd_intf_linkstatus
$_nd_intf_linestatus
$_nd_local_intf_name
$_nd_short_local_intf_name
$_nd_port_id
LLDP EVENT VARIABLES:
$_nd_protocol
$_nd_proto_notif
$_nd_proto_new_entry
$_nd_lldp_chassis_id
$_nd_lldp_system_name
$_nd_lldp_system_description
$_nd_lldp_ttl
$_nd_lldp_port_description
Using above command we can get a list of all the built-in variables and use them according to our automation needs.
EEM threads and VTY lines
In most Cisco devices we have 16 VTY lines. We need to beware of an extreme case scenario. For example - our switch has deleted 20 new LLDP neighbors at the same time. Then for each LLDP neighbor update applet operation; EEM will create a thread, use one VTY lines. But we have maximum 16 lines and we require 20 threads with 20 vty lines. In such case; our applet execution will fail. Instead what we can configure is that - EEM can create maximum 5 threads and use 5 vty lines. Other update operations/threads will wait until current ones are finished; then EEM will create new threads for the updates with are in queue. In this case; we will use queuing so that EEM does not exhaust VTY lines. The command to configure maximum number of threads of EEM is -
!!! Allow maximum of 5 threads/5 vty lines of EEM
SW01(config)#event manager scheduler applet thread class default number 5
Now time to test our LLDP update/delete applet. We forcefully clear LLDP table; so that we can see both remove/add operation.
SW01#clear lldp table
After some time when LLDP neighbor table is populated - We can see our interface description -
SW01#show interfaces description
Interface Status Protocol Description
Gi0/0 down down
Gi0/1 up up SW02-Gi0/1
Gi0/2 up up SW03-Gi0/2
Gi0/3 down down
Gi1/0 down down
Gi1/1 down down
Gi1/2 down down
Gi1/3 down down
We can also see the syslog messages from our applets -
SW01#show logging | include %HA_EM-6-LOG
Jul 5 23:41:54.072: %HA_EM-6-LOG: Applet_LLDP_Port_Description_Remove: EEM script deleted interface description for - GigabitEthernet0/1
Jul 5 23:41:56.021: %HA_EM-6-LOG: Applet_LLDP_Port_Description_Remove: EEM script deleted interface description for - GigabitEthernet0/2
Jul 5 23:42:17.156: %HA_EM-6-LOG: Applet_LLDP_Port_Description_Add: EEM applet added interface description for - GigabitEthernet0/1
Jul 5 23:42:23.222: %HA_EM-6-LOG: Applet_LLDP_Port_Description_Add: EEM applet added interface description for - GigabitEthernet0/2
Verification
We can view all our configured EEM policies in the device using command -
SW01#show event manager policy registered (output truncated)
No. Class Type Event Type Trap Time Registered Name
1 applet user none Off Mon Jul 5 09:25:36 Applet_Syslog
policyname {Applet_Syslog} sync {yes}
maxrun 20.000
action 1.0 comment "Generate a syslog message with EEM applet"
action 1.1 syslog msg "Welcome to EEM with Applet!!!"
3 applet user timer cron Off Mon Jul 5 15:03:28 Applet_Shutdown_Gi0/1
cron entry {0 20 * * *}
maxrun 20.000
action 1.0 comment "Shutdown Gi0/1 port at 20:00 everyday"
action 1.1 cli command "enable"
action 1.2 cli command "configure terminal"
action 1.3 cli command "interface Gi0/1"
action 1.4 cli command "shutdown"
action 1.5 cli command "end"
action 1.6 syslog msg "Interface Gi1/0/1 has been shutdown with scheduled applet"
As expected detailed debugging of EEM also provided by Cisco.
!!! Turn on EEM debugging for CLI operations. Our applets use CLI.
SW01#debug event manager action cli
Debug EEM action cli debugging is on
!!! Filtering EEM CLI debug logs which shows the CLI commands executed by Applet.
SW01#show logging | include DEBUG(cli_lib)*
Jul 5 23:56:40.607: %HA_EM-6-LOG: Applet_LLDP_Port_Description_Add : DEBUG(cli_lib) : : OUT :
Jul 5 23:56:40.607: %HA_EM-6-LOG: Applet_LLDP_Port_Description_Add : DEBUG(cli_lib) : : OUT : SW01>
Jul 5 23:56:40.607: %HA_EM-6-LOG: Applet_LLDP_Port_Description_Add : DEBUG(cli_lib) : : IN : SW01>enable
Jul 5 23:56:40.618: %HA_EM-6-LOG: Applet_LLDP_Port_Description_Add : DEBUG(cli_lib) : : OUT : SW01#
Jul 5 23:56:40.618: %HA_EM-6-LOG: Applet_LLDP_Port_Description_Add : DEBUG(cli_lib) : : IN : SW01#configure terminal
Jul 5 23:56:40.633: %HA_EM-6-LOG: Applet_LLDP_Port_Description_Add : DEBUG(cli_lib) : : OUT : Enter configuration commands, one per line. End with CNTL/Z.
Jul 5 23:56:40.633: %HA_EM-6-LOG: Applet_LLDP_Port_Description_Add : DEBUG(cli_lib) : : OUT : SW01(config)#
Jul 5 23:56:40.633: %HA_EM-6-LOG: Applet_LLDP_Port_Description_Add : DEBUG(cli_lib) : : IN : SW01(config)#interface GigabitEthernet0/1
Jul 5 23:56:40.744: %HA_EM-6-LOG: Applet_LLDP_Port_Description_Add : DEBUG(cli_lib) : : OUT : SW01(config-if)#
Jul 5 23:56:40.744: %HA_EM-6-LOG: Applet_LLDP_Port_Description_Add : DEBUG(cli_lib) : : IN : SW01(config-if)#description SW02-Gi0/1
Jul 5 23:56:40.857: %HA_EM-6-LOG: Applet_LLDP_Port_Description_Add : DEBUG(cli_lib) : : OUT : SW01(config-if)#
Jul 5 23:56:40.857: %HA_EM-6-LOG: Applet_LLDP_Port_Description_Add : DEBUG(cli_lib) : : IN : SW01(config-if)#end
Jul 5 23:56:40.867: %HA_EM-6-LOG: Applet_LLDP_Port_Description_Add : DEBUG(cli_lib) : : OUT : SW01#
Jul 5 23:56:40.867: %HA_EM-6-LOG: Applet_LLDP_Port_Description_Add : DEBUG(cli_lib) : : IN : SW01#write memory
That's it for today. Happy automation with Cisco EEM.
References
Comments
Post a Comment