I wish I were about to write a blog that started with “This is so easy – you need to be doing this right now,” but I think there is a reason that this topic doesn’t appear on any Cisco exams until CCIE. This is simply an expert level task. But with a “can-do” attitude, you, too, can survive getting this to work.
So let’s not dilly dally anymore, shall we? Our primary objective is that when some sort of event happens that can fire off an EEM applet, it actually runs a Python script. The thing is, the Python script is deployed from Guestshell, so our first objective is to actually enable Guestshell, which runs as an application on the Cisco IOS-XE device. Beyond that, we should explain how the Guestshell “app” actually works, but in due time.
So first, thing is first. Make sure your device has an external facing IP address with internet access. Set a default route, and make sure DNS resolution can occur. Your device should be able to ping “dataknox.dev” for example.
conf t
! ASSIGN AN IP ADDRESS TO AN INTERFACE THAT CAN REACH THE INTERNET
! SET DEFAULT ROUTE
! SET DNS SERVER
Now it is time to configure the Guestshell application. The first step is to enable IOX, which is basically the app hosting or virtualization platform on Cisco IOS-XE devices. Then, we will create the default gateway for the Guestshell app. This will be the VirtualPortGroup interface. I cannot stress this enough – this interface will be our app’s default gateway. Therefore, for our app to speak to the outside world, we need to configure NAT (PAT).
iox
do show iox
interface virtualportgroup 0
ip add 192.168.144.15 255.255.255.0
no shut
ip nat inside
! go to outside int
int gig 1
ip nat outside
exit
ip access-list standard NATOUT
permit 192.168.0.0 0.0.255.255
exit
ip nat inside source list NATOUT interface gigabitEthernet 1 overload
Now comes a weird feature. At the time that I discovered this was “a thing” only God and I knew what I was doing. Now only God knows. You need to enable HTTP services for the Guestshell Python module to communicate to the IOS-XE operation. Not HTTPS. It has to be HTTP. So if you want Python to run any sort of CLI command, you need to enable HTTP.
ip http server
So with all of those pieces in place, it is time to create our Guestshell “app” and we make sure it is configured with the default gateway of our VirtualPortGroup.
app-hosting appid guestshell
vnic gateway1 virtualportgroup 0 guest-interface 0 guest-ipaddress 192.168.144.2 netmask 255.255.255.0 gateway 192.168.144.15 name-server 8.8.8.8 default
resource profile custom cpu 1500 memory 512
Huge command, right? What the Hell just happened here? We created the app “guestshell,” and then we configured it’s vNIC (similar to a virtual NIC in a VM). We assigned it’s IP address and notice the gateway is the same IP Address of the VritualPortGroup interface. Lastly we give the app some CPU and RAM allocations. Next up is a very important step. For whatever reason, every time I have run this command, it assigns all these configs to the wrong guest-interface. It assigns it to guest-interface 1, when we clearly typed guest-interface 0. Gotta fix it.
no app-default-gateway 192.168.144.15 guest-interface 1
app-default-gateway 192.168.144.15 guest-interface 0
end
Now that we are back on privileged mode, it is time to turn on our application and jump into it. There’s not much to it, but the real magic really begins here.
guestshell enable
! wait until you receive a syslog message saying that it is alive
guestshell
Ok, we are now officially in Guestshell, and this should look and feel like any other Unix/Linux box you’ve worked with up till this point. So let’s create a Python script that will fire off when an EEM applet detects that an OSPF adjacency has changed. This script will make an HTTP POST Request to send an alert to a listening API when the EEM applet fires off.
[guestshell@guestshell ~]$ sudo pip3 install requests
[guestshell@guestshell ~]$ vi ospfsender.py
import requests
import json
payload={
"hostname":"CSR1",
"messages":"OSPF is flapping"
}
headers={"Content-Type":"application/json","Accept":"application/json"}
r = requests.post(url="http://10.10.21.196:5000/ios",data=json.dumps(payload),headers=headers,verify=False)
print(r.text)
~
~
~
~
~
~
~
~
~
~
~
~
Just like all painful experiences with Vi/Vim, make sure you press Esc to exit edit mode, and then type :wq to Write and Quit the file. You now have a Python script on your box. You can exit out of Guestshell with exit, and then test your script with the “guestshell run” command.
guestshell run python3 /home/guestshell/ospfsender.py
So our final step is to run the python script with the above command in the event that our EEM applet detects that an OSPF adjacency has gone down. Important note: you need to run this from Privileged Mode.
event manager applet OSPF
event syslog pattern "from FULL to DOWN"
action 0 cli command "en"
action 1 syslog msg "OSPF Applet fired"
action 2 cli command "guestshell run python3 /home/guestshell/ospfsender.py"
And THAT. IS. IT. That’s what you have to go through to enable Guestshell on Cisco IOS-XE, create some on-box Python script, and trigger it with an EEM applet.
It is such a great resource which you are providing and you give it away for free. I take pleasure in seeing web sites that fully grasp the worth of offering a high quality resource for free of charge.