One of my current projects at work is to build up Zabbix as an alerting solution.
This includes using Zabbix to raise incidents in ServiceNow for any alerts that come through.
Initially, I thought that I would need to do lots of scripting, but it turns out I only had to write a simple script to allow Zabbix to raise incidents in ServiceNow.
This was largely thanks to pre-built Python modules that the community have built to allow easy integrations, namely ZabbixAPI
and Python-Servicenow
.
These 2 libraries made integration easy because they allowed me to concentrate more on the code to join the 2 systems rather than having to figure out how to make them talk to Python, and then talk to each other.
The integration itself will take an alert that is generated by Zabbix and insert the data into ServiceNow as an incident.
Configuring Zabbix
- Copy the snippet at the bottom of this post into a file in
/usr/lib/zabbix/alertscripts
. I’ve named mineservicenowapi.py
. - Create a new Media Type.
Create a new media type by going to Administration => Media types, and click on Create media type.
Give the Media Type a name, selectScript
for the Type, and put in the name of the file. Using my example, it would beservicenowapi.py
- Assign the new Media Type to a user.
The user’s “Send to” for the media type will define the assignment group in ServiceNow.
Click on Administration => Users, select Users in the drop down on the top right, and click on a user. Once you’re in the user’s configuration page, click on the Media tab, and then click on ‘Add’.
Select the new Media Type from the type drop down, and then enter in the ServiceNow Assignment Group in the ‘Send To’ box, and click ‘Add’. - Create or modify an existing action to start sending incidents to ServiceNow.
Click on Configuration => Actions, and open up an Action. Click on the Operations Tab, and click on “New”.
Click on “Add” in the Send To Users section, and choose the user that has the ServiceNow Media type set up.
Select the ServiceNow action in the “Send only to” box, and then click on the “Add” button to add the action to the list of actions.
Once the action has been setup, click on Save.
Once the alert is all set up, whenever the alert is triggered, the script should log an incident directly into ServiceNow.
servicenowapi.py
The below code should be copied and pasted into a file to be used as the script for the Media Type.
#!/usr/bin/python
import zapi
import datetime
import sys
import urllib2
import os
import servicenow.Connection
import servicenow.ServiceNow
##
## I've used logging for my own setup, but I've commented it out so that it won't spam a log file unless you uncomment it.
## Just make sure the location that you're storing the logfile is writable by the zabbix user
## In this example, I've used /usr/lib/zabbix/logfiles but this could be anywhere writable by the zabbix user
#f = open('/usr/lib/zabbix/logfiles/snow.log','a')
#f.write('\n\nScript Start :: '+datetime.datetime.now().ctime()+'\n\n')
#f.write(','.join(sys.argv)+'\n')
## Zabbix Passes the details via command line arguments.
assignmentgroup = sys.argv[1]
description = sys.argv[2]
detail = sys.argv[3]
## Set Up your Zabbix details
zabbixsrv = "127.0.0.1"
zabbixun = "Admin"
zabbixpw = "zabbix"
## Set up your ServiceNow instance details
## For Dublin+ instances, connect using JSONv2, otherwise use JSON
username = "username"
password = "password"
instance = "instance"
api = "JSONv2"
## I've configured Zabbix to only pass the Event ID in the message body.
## If you want more detail in the body of the incident in ServiceNow, you'll need to make sure that eventid is parsed out of detail correctly.
eventid = detail
#f.write('trying to connect to servicenow\n')
try:
conn = servicenow.Connection.Auth(username=username,password=password,instance=instance, api=api)
except:
print "Error Connecting to ServiceNow\n"
#f.write("Error Connecting to ServiceNow\n")
#f.write('trying to create incident instance\n')
try:
inc = servicenow.ServiceNow.Incident(conn)
except:
print "Error creating incident instance\n"
#f.write("Error creating incident instance\n")
#f.write('trying to create new incident\n')
## This is where the fun starts.
## You'll need to set up the following section with the correct form fields, as well as the default values
try:
newinc = servicenow.ServiceNow.Incident.create(inc, { \
"short_description":description, \
"description":detail, \
"priority":"3", \
"u_requestor":"autoalert", \
"u_contact_type":"Auto Monitoring", \
"assignment_group": assignmentgroup})
#f.write("\n\n"+str(newinc)+"\n\n")
except Exception as e:
print "Error creating new incident in ServiceNow\n"
print str(e)
#f.write("Error creating new incident in ServiceNow\n")
#f.write(str(e)+"\n")
## This script will retrieve the new incident number from servicenow and put it back into zabbix as an acknowledgement
try:
newincno = newinc["records"][0]["number"]
except:
print "unable to retrieve new incident number\n"
#f.write("unable to retrieve new incident number\n")
zabbix = zapi.ZabbixAPI(url='http://'+zabbixsrv+'/zabbix',user=zabbixun,password=zabbixpw)
zabbix.login()
#f.write('Acknowledging event '+eventid+'\n')
zabbix.Event.acknowledge({'eventids':[eventid],'message':newincno})
#f.write('\n\nScript End :: '+datetime.datetime.now().ctime()+'\n\n')
#f.close()