Over the holidays I got around to updating some old Cisco Spark stuff over to Webex Teams. Since I haven’t made a post a little bit, I figured I would share some of the fun with you all.
Today we will use Guestshell with EEM to have the router notify us in Webex Teams when the routing table changes!
Topology
The topology for this one doesn’t really matter unless your following along exactly, I’m using 4 x CSR1000v routers running 16.10.1b (I like new toys), and each router has two connections to its neighbor so we have some routes to play with, lastly the internet access is through the MGMT VRF.
The Boring Basic Setup Stuff
CSR01
CSR01#sh ip int br | ex unass Interface IP-Address OK? Method Status Protocol GigabitEthernet1 10.20.2.81 YES manual up up GigabitEthernet2.812 10.8.12.1 YES manual up up GigabitEthernet2.912 10.9.12.1 YES manual up up Loopback0 10.255.255.111 YES manual up up Loopback11 192.168.11.1 YES manual up up Loopback12 192.168.12.1 YES manual up up Loopback13 192.168.13.1 YES manual up up
CSR02
CSR02#sh ip int br | ex unass Interface IP-Address OK? Method Status Protocol GigabitEthernet1 10.20.2.82 YES manual up up GigabitEthernet2.812 10.8.12.2 YES manual up up GigabitEthernet2.823 10.8.23.2 YES manual up up GigabitEthernet2.912 10.9.12.2 YES manual up up GigabitEthernet2.923 10.9.23.2 YES manual up up Loopback0 10.255.255.112 YES manual up up Loopback21 192.168.21.1 YES manual up up Loopback22 192.168.22.1 YES manual up up Loopback23 192.168.23.1 YES manual up up
CSR03
CSR03#sh ip int br | ex unass Interface IP-Address OK? Method Status Protocol GigabitEthernet1 10.20.2.83 YES manual up up GigabitEthernet2 10.255.123.3 YES manual up up GigabitEthernet2.823 10.8.23.3 YES manual up up GigabitEthernet2.834 10.8.34.3 YES manual up up GigabitEthernet2.934 10.9.34.3 YES manual up up Loopback0 10.255.255.113 YES manual up up Loopback31 192.168.31.1 YES manual up up Loopback32 192.168.32.1 YES manual up up Loopback33 192.168.33.1 YES manual up up
CSR04
CSR04#sh ip int br | ex unass Interface IP-Address OK? Method Status Protocol GigabitEthernet1 10.20.2.84 YES manual up up GigabitEthernet2.834 10.8.34.4 YES manual up up GigabitEthernet2.934 10.9.34.4 YES manual up up Loopback0 10.255.255.114 YES manual up up Loopback41 192.168.41.1 YES manual up up Loopback42 192.168.42.1 YES manual up up Loopback43 192.168.43.1 YES manual up up
The Fun Guestshell and VRF Stuff!
This is where we will focus on getting our guestshell up and online! Since the steps will be largely the same I will focus on CSR01 from this point on unless we need to do something on another router.
Creating the VRF
First things first, we’ll create a MGMT VRF for the IPv4 address family.
CSR01(config)#vrf definition MGMT CSR01(config-vrf)#address-family ipv4 CSR01(config-vrf-af)#exit CSR01(config-vrf)#exit
Next I’ll add the MGMT interface to the VRF and give it an IP address. We will also set ip nat outside on the interface since it will be our internet interface.
CSR01(config)#int g1 CSR01(config-if)#vrf forwarding MGMT CSR01(config-if)#ip add 10.20.2.81 255.255.255.0 CSR01(config-if)#ip nat outside
Also we will need a default route out to the internet.
CSR01(config)#ip route vrf MGMT 0.0.0.0 0.0.0.0 10.20.2.1
Creating the Guestshell
Guestshell uses a Virtual Portgroup interface as its default gateway, we will create the interface, put it in the MGMT VRF to make life easier, and setup NAT to get online. Then we will make the actual guestshell.
CSR01(config)#interface VirtualPortGroup0 CSR01(config-if)# vrf forwarding MGMT CSR01(config-if)# ip address 192.168.123.1 255.255.255.0 CSR01(config-if)# ip nat inside CSR01(config-if)#exit
Then we’ll setup the rest of NAT, nothing too interesting here except I use the vrf keyword since the interfaces are in the MGMT VRF.
CSR01(config)#ip access-list extended ACL_GUESTSHELL_NAT CSR01(config-ext-nacl)# permit ip 192.168.123.0 0.0.0.255 any CSR01(config-ext-nacl)#exit CSR01(config)#ip nat inside source list ACL_GUESTSHELL_NAT interface GigabitEthernet1 vrf MGMT overload
Note: Guestshell has went through several config iterations over the IOS-XE trains, Cisco seems to be settling on the app-hosting method for configuring the shell but who knows! If you are using another IOS version then you may need to lookup your exact steps, for example, 16.6.x uses the guestshell enable command to supply everything.
My IOS-XE uses app-hosting to provide the guestshell configuration using a rather long command like this:
CSR01(config)#iox CSR01(config)#app-hosting appid guestshell CSR01(config-app-hosting)#vnic gateway1 virtualportgroup 0 guest-interface 0 guest-ipaddress 192.168.123.101 netmask 255.255.255.0 gateway 192.168.123.1 name-server 8.8.8.8 CSR01(config-app-hosting)#end CSR01#guestshell enable
After a few minutes we should have a happy guestshell we can reach! It is worth noting that since we are doing NAT we can use the same IP for the shell on each router but there is no harm in changing the host IP for each shell.
The Script Part!
Now we have our guestshell we can focus on the point of this post!
If you haven’t used guestshell before, you can enter it with the guestshell command, one thing to note is the console will probably wrap when we do longer commands just like this. 🙁
CSR01#guestshell eamsjtshell@guestshell ~]$ sudo yum update -y && sudo pip install ipython webext
We can use the stty command to give us more room to work with.
[guestshell@guestshell ~]$ stty cols 510 [guestshell@guestshell ~]$ sudo yum update -y && sudo pip install ipython webexteamssdk Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile * base: mirror.its.sfu.ca * extras: mirror.it.ubc.ca * updates: mirror.csclub.uwaterloo.ca
That is better! Go ahead and update the linux shell and install the webexteamssdk, I also like installing ipython, try it!
To make sure the router can reach the script we will make a scripts folder in bootflash
[guestshell@guestshell ~]$ mkdir /bootflash/scripts/
The script itself just using the WebexTeamsSDK and ArgumentParser to pass along the arguments we will send it.
[guestshell@guestshell scripts]$ cat /bootflash/scripts/webex_checkin.py from webexteamssdk import WebexTeamsAPI if __name__=='__main__': # Use ArgParse to retrieve command line parameters. from argparse import ArgumentParser parser = ArgumentParser("Webex Check In") # Retrieve the Webex Token and Destination Email parser.add_argument( "-t", "--token", help="Webex Authentication Token", required=True ) # Retrieve the Webex Token and Destination Email parser.add_argument( "-e", "--email", help="Email to Send to", required=True ) parser.add_argument( "-m", "--message", help="Enter Message", required=True ) args = parser.parse_args() token = args.token email = args.email message = args.message api = WebexTeamsAPI(access_token=token) api.messages.create(toPersonEmail=email, markdown=message)
The script expects the following syntax:
python webex_checkin.py -t “<token>” -e “<email>” -m “<message”>
At this point we are good to start working on the Webex Teams stuff!
The Webex Teams Stuff
Now we have the basic setup done, we now need to create some Webex Team bots that EEM can talk to. Go to https://developer.webex.com and sign in with your Webex Teams account…don’t have one? Now is the time to signup…I’ll wait.
Once your in go to the app section, in my case it is the kitty in the corner, and create a new application. Since I’m focusing on CSR01 I’ll just recreate that one.
Select Create a Bot
In the New Bot page, we need to give it a Name, Username, pick an icon, and add a description. I’m not terribly creative today so I’ll use just use CSR01 and pick a default icon. These fields control what the bot looks like when talking to you.
Once the bot is created, we need to copy the Access Token, copy it and keep it handy. If you lose it then you can regenerate the token from this page.
The EEM Config
We are in the home stretch now! We just need to create some EEM applets but first we need to create some environment variables for EEM to use the script easier.
We will create 4 variables:
_webex_token – This is the Access Token from our Bot for the router. I would recommend doing this before you loss the token!
_webex_email – This is the email address that the bot will send the message to, in this case its my test webex account.
_webex_script – This is the path to the script along with its name
_webex_quote – This is a workaround to deal with nesting commands on to each other since we will already have a quote open when we call the guestshell run command.
Note: If you have shell processing full / terminal shell on then you’ll want to do a \” so IOS.sh doesn’t get confused.
CSR01(config)#event manager environment _webex_email "donald.robb@shaw.ca" CSR01(config)#event manager environment _webex_script "/bootflash/scripts/webex_checkin.py" CSR01(config)#event manager environment _webex_quote " CSR01(config)#event manager environment _webex_token "ZjkxNDc2NGUtNWE5ZC00NzdlLTkyNjEtYTk0YzE2YjZhMzVhZjhkYTRjNjQtYTk4_PF84_consumer"
Finally it is time to make our simple EEM applets! I have covered EEM before so I won’t get too much into it. What I’m doing here is using the routing network event to notify me whenever any new network appears in the RIB. If you want you can change the 0.0.0.0/0 to a more specific network or add the protocol keyword if you want to restrict the event to a particular protocol like OSPF.
Action 000 creates a variable called _webex_route_add_message and stores the route added message that is constructed from the built-in routing related variables.
Action 015 is optional and just outputs the same message to the console so we know things are changing on the network .
Action 020 calls the script using the guestshell run command. We then call the variables we made above. Since the command is already in quotes we use the _webex_quote to add quotes into embedded command.
I should also mention that you can skip a lot of the variables and it it directly in the applet but using variables is a lot cleaner.
event manager applet WEBEX-ROUTE-ADD event routing network 0.0.0.0/0 type add le 32 action 000 set _webex_route_add_message "Route $_routing_network/$_routing_prefix_len has been added via $_routing_protocol" action 010 cli command "enable" action 015 puts "$_webex_route_add_message" action 020 cli command "guestshell run python $_webex_script -t $_webex_token -e $_webex_email -m $_webex_quote$_webex_route_add_message$_webex_quote"
I’ll also make another applet that monitors for when networks are removed.
event manager applet WEBEX-ROUTE-DEL event routing network 0.0.0.0/0 type remove le 32 action 000 set _webex_route_del_message "Route $_routing_network/$_routing_prefix_len has been removed from $_routing_protocol" action 010 cli command "enable" action 015 puts "$_webex_route_del_message" action 020 cli command "guestshell run python $_webex_script -t $_webex_token -e $_webex_email -m $_webex_quote$_webex_route_del_message$_webex_quote"
As well as one when the route is modified.
event manager applet WEBEX-ROUTE-MOD event routing network 0.0.0.0/0 type modify le 32 action 000 set _webex_route_mod_message "Route $_routing_network/$_routing_prefix_len has modified, it is using $_routing_protocol" action 010 cli command "enable" action 015 puts "$_webex_route_mod_message" action 020 cli command "guestshell run python $_webex_script -t $_webex_token -e $_webex_email -m $_webex_quote$_webex_route_mod_message$_webex_quote"
Testing it out!
To try this out we will turn OSPF on everywhere and see if we get messages in Webex Teams!
CSR01(config)#router ospf 1 CSR01(config-router)#network 0.0.0.0 0.0.0.0 area 0 CSR01(config-router)# *Dec 28 20:34:32.320: %OSPF-5-ADJCHG: Process 1, Nbr 10.255.255.112 on GigabitEthernet2.912 from LOADING to FULL, Loading Done *Dec 28 20:34:32.320: %OSPF-5-ADJCHG: Process 1, Nbr 10.255.255.112 on GigabitEthernet2.812 from LOADING to FULL, Loading Done *Dec 28 20:34:32.591: %HA_EM-6-LOG: WEBEX-ROUTE-ADD: Route 192.168.43.1/32 has been added via OSPF *Dec 28 20:34:32.591: %HA_EM-6-LOG: WEBEX-ROUTE-ADD: Route 192.168.42.1/32 has been added via OSPF *Dec 28 20:34:32.591: %HA_EM-6-LOG: WEBEX-ROUTE-ADD: Route 192.168.41.1/32 has been added via OSPF *Dec 28 20:34:32.592: %HA_EM-6-LOG: WEBEX-ROUTE-ADD: Route 192.168.33.1/32 has been added via OSPF *Dec 28 20:34:32.592: %HA_EM-6-LOG: WEBEX-ROUTE-ADD: Route 192.168.32.1/32 has been added via OSPF *Dec 28 20:34:48.513: %HA_EM-6-LOG: WEBEX-ROUTE-ADD: Route 192.168.31.1/32 has been added via OSPF *Dec 28 20:34:52.233: %HA_EM-6-LOG: WEBEX-ROUTE-ADD: Route 192.168.23.1/32 has been added via OSPF *Dec 28 20:34:52.733: %HA_EM-6-LOG: WEBEX-ROUTE-ADD: Route 192.168.22.1/32 has been added via OSPF *Dec 28 20:34:52.740: %HA_EM-6-LOG: WEBEX-ROUTE-ADD: Route 192.168.21.1/32 has been added via OSPF *Dec 28 20:34:52.740: %HA_EM-6-LOG: WEBEX-ROUTE-ADD: Route 10.255.255.114/32 has been added via OSPF *Dec 28 20:35:08.045: %HA_EM-6-LOG: WEBEX-ROUTE-ADD: Route 10.255.255.113/32 has been added via OSPF *Dec 28 20:35:09.649: %HA_EM-6-LOG: WEBEX-ROUTE-ADD: Route 10.255.255.112/32 has been added via OSPF *Dec 28 20:35:12.783: %HA_EM-6-LOG: WEBEX-ROUTE-ADD: Route 10.255.123.0/24 has been added via OSPF *Dec 28 20:35:12.784: %HA_EM-6-LOG: WEBEX-ROUTE-ADD: Route 10.9.23.0/24 has been added via OSPF *Dec 28 20:35:12.784: %HA_EM-6-LOG: WEBEX-ROUTE-ADD: Route 10.8.34.0/24 has been added via OSPF *Dec 28 20:35:25.996: %HA_EM-6-LOG: WEBEX-ROUTE-ADD: Route 10.9.34.0/24 has been added via OSPF *Dec 28 20:35:29.409: %HA_EM-6-LOG: WEBEX-ROUTE-ADD: Route 10.8.23.0/24 has been added via OSPF
We will also remove OSPF on CSR01 to test removal!
CSR01(config-router)#no router ospf 1 CSR01(config)# *Dec 28 20:37:02.878: %OSPF-5-ADJCHG: Process 1, Nbr 10.255.255.112 on GigabitEthernet2.912 from FULL to DOWN, Neighbor Down: Interface down or detached *Dec 28 20:37:02.878: %OSPF-5-ADJCHG: Process 1, Nbr 10.255.255.112 on GigabitEthernet2.812 from FULL to DOWN, Neighbor Down: Interface down or detached CSR01(config)# *Dec 28 20:37:02.903: %HA_EM-6-LOG: WEBEX-ROUTE-DEL: Route 10.8.23.0/24 has been removed from OSPF *Dec 28 20:37:02.904: %HA_EM-6-LOG: WEBEX-ROUTE-DEL: Route 10.8.34.0/24 has been removed from OSPF *Dec 28 20:37:02.904: %HA_EM-6-LOG: WEBEX-ROUTE-DEL: Route 10.9.23.0/24 has been removed from OSPF *Dec 28 20:37:02.904: %HA_EM-6-LOG: WEBEX-ROUTE-DEL: Route 10.9.34.0/24 has been removed from OSPF *Dec 28 20:37:02.905: %HA_EM-6-LOG: WEBEX-ROUTE-DEL: Route 10.255.123.0/24 has been removed from OSPF *Dec 28 20:37:19.523: %HA_EM-6-LOG: WEBEX-ROUTE-DEL: Route 10.255.255.112/32 has been removed from OSPF *Dec 28 20:37:22.244: %HA_EM-6-LOG: WEBEX-ROUTE-DEL: Route 10.255.255.113/32 has been removed from OSPF *Dec 28 20:37:22.855: %HA_EM-6-LOG: WEBEX-ROUTE-DEL: Route 10.255.255.114/32 has been removed from OSPF *Dec 28 20:37:22.855: %HA_EM-6-LOG: WEBEX-ROUTE-DEL: Route 192.168.21.1/32 has been removed from OSPF *Dec 28 20:37:22.856: %HA_EM-6-LOG: WEBEX-ROUTE-DEL: Route 192.168.22.1/32 has been removed from OSPF *Dec 28 20:37:38.115: %HA_EM-6-LOG: WEBEX-ROUTE-DEL: Route 192.168.23.1/32 has been removed from OSPF *Dec 28 20:37:41.930: %HA_EM-6-LOG: WEBEX-ROUTE-DEL: Route 192.168.31.1/32 has been removed from OSPF *Dec 28 20:37:42.231: %HA_EM-6-LOG: WEBEX-ROUTE-DEL: Route 192.168.32.1/32 has been removed from OSPF *Dec 28 20:37:42.234: %HA_EM-6-LOG: WEBEX-ROUTE-DEL: Route 192.168.33.1/32 has been removed from OSPF *Dec 28 20:37:43.048: %HA_EM-6-LOG: WEBEX-ROUTE-DEL: Route 192.168.41.1/32 has been removed from OSPF *Dec 28 20:37:57.191: %HA_EM-6-LOG: WEBEX-ROUTE-DEL: Route 192.168.42.1/32 has been removed from OSPF *Dec 28 20:37:59.762: %HA_EM-6-LOG: WEBEX-ROUTE-DEL: Route 192.168.43.1/32 has been removed from OSPF
And we get our notifications from CSR01 (and the other routers if you did them all)
Final Thoughts
Today we played with Guestshell, EEM, and Webex Teams to explore some of the more interesting guestshell capabilities. You can easily take this and extend it by adding other applets that monitor performance on the router or SLA status. Perhaps in another post we will have so we can ask the router for info from Webex Teams.