Created
December 22, 2015 22:47
-
-
Save jcurry/ebb20c6665ba249bce55 to your computer and use it in GitHub Desktop.
JSON API code to get Zenoss events
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# Zenoss-4.x JSON API Example (python) | |
# | |
# To quickly explore, execute 'python -i get_events.py | |
# | |
# >>> z = getEventsWithJSON() | |
# >>> events = z.get_events() | |
# etc. | |
import json | |
import urllib | |
import urllib2 | |
from optparse import OptionParser | |
import pprint | |
#ZENOSS_INSTANCE = 'http://ZENOSS-SERVER:8080' | |
# Change the next line(s) to suit your environment | |
# | |
#ZENOSS_INSTANCE = 'http://zen42.class.example.org:8080' | |
ZENOSS_INSTANCE = 'https://zen42.class.example.org' | |
ZENOSS_USERNAME = 'admin' | |
ZENOSS_PASSWORD = 'zenoss' | |
ROUTERS = { 'MessagingRouter': 'messaging', | |
'EventsRouter': 'evconsole', | |
'ProcessRouter': 'process', | |
'ServiceRouter': 'service', | |
'DeviceRouter': 'device', | |
'NetworkRouter': 'network', | |
'TemplateRouter': 'template', | |
'DetailNavRouter': 'detailnav', | |
'ReportRouter': 'report', | |
'MibRouter': 'mib', | |
'ZenPackRouter': 'zenpack' } | |
class getEventsWithJSON(): | |
def __init__(self, debug=False): | |
""" | |
Initialize the API connection, log in, and store authentication cookie | |
""" | |
# Use the HTTPCookieProcessor as urllib2 does not save cookies by default | |
self.urlOpener = urllib2.build_opener(urllib2.HTTPCookieProcessor()) | |
if debug: self.urlOpener.add_handler(urllib2.HTTPHandler(debuglevel=1)) | |
self.reqCount = 1 | |
# Contruct POST params and submit login. | |
loginParams = urllib.urlencode(dict( | |
__ac_name = ZENOSS_USERNAME, | |
__ac_password = ZENOSS_PASSWORD, | |
submitted = 'true', | |
came_from = ZENOSS_INSTANCE + '/zport/dmd')) | |
self.urlOpener.open(ZENOSS_INSTANCE + '/zport/acl_users/cookieAuthHelper/login', | |
loginParams) | |
def _router_request(self, router, method, data=[]): | |
if router not in ROUTERS: | |
raise Exception('Router "' + router + '" not available.') | |
# Contruct a standard URL request for API calls | |
req = urllib2.Request(ZENOSS_INSTANCE + '/zport/dmd/' + | |
ROUTERS[router] + '_router') | |
# NOTE: Content-type MUST be set to 'application/json' for these requests | |
req.add_header('Content-type', 'application/json; charset=utf-8') | |
# Convert the request parameters into JSON | |
reqData = json.dumps([dict( | |
action=router, | |
method=method, | |
data=data, | |
type='rpc', | |
tid=self.reqCount)]) | |
# Increment the request count ('tid'). More important if sending multiple | |
# calls in a single request | |
self.reqCount += 1 | |
# Submit the request and convert the returned JSON to objects | |
return json.loads(self.urlOpener.open(req, reqData).read()) | |
def get_events(self, filter={}, sort='severity', dir='DESC', arch=False, lim=1000): | |
""" Use EventsRouter action (Class) and query method found | |
in JSON API docs on Zenoss website: | |
query(self, limit=0, start=0, sort='lastTime', dir='desc', params=None, | |
archive=False, uid=None, detailFormat=False) | |
Parameters: | |
limit (integer) - (optional) Max index of events to retrieve (default: 0) | |
start (integer) - (optional) Min index of events to retrieve (default: 0) | |
sort (string) - (optional) Key on which to sort the return results (default: 'lastTime') | |
dir (string) - (optional) Sort order; can be either 'ASC' or 'DESC' (default: 'DESC') | |
params (dictionary) - (optional) Key-value pair of filters for this search. (default: None) | |
params are the filters to the query method and can be found in the _buildFilter method. | |
severity = params.get('severity'), | |
status = [i for i in params.get('eventState', [])], | |
event_class = filter(None, [params.get('eventClass')]), | |
Note that the time vaues can be ranges where a valid range would be | |
'2012-09-07 07:57:33/2012-11-22 17:57:33' | |
first_seen = params.get('firstTime') and self._timeRange(params.get('firstTime')), | |
last_seen = params.get('lastTime') and self._timeRange(params.get('lastTime')), | |
status_change = params.get('stateChange') and self._timeRange(params.get('stateChange')), | |
uuid = filterEventUuids, | |
count_range = params.get('count'), | |
element_title = params.get('device'), | |
element_sub_title = params.get('component'), | |
event_summary = params.get('summary'), | |
current_user_name = params.get('ownerid'), | |
agent = params.get('agent'), | |
monitor = params.get('monitor'), | |
fingerprint = params.get('dedupid'), | |
tags = params.get('tags'), | |
details = details, | |
archive (boolean) - (optional) True to search the event history table instead of active events (default: False) | |
uid (string) - (optional) Context for the query (default: None) | |
Returns: dictionary | |
Properties: | |
events: ([dictionary]) List of objects representing events | |
totalCount: (integer) Total count of events returned | |
asof: (float) Current time | |
""" | |
#data = dict(start=0, limit=1000) | |
#data = dict(start=0, limit=1000) | |
data = dict(start=0, archive=arch, limit=lim) | |
if sort: data['sort'] = sort | |
if dir: data['dir'] = dir | |
data['params'] = filter | |
#print 'data[params] is %s \n' % (data['params']) | |
#print 'data is %s \n' % (data) | |
return self._router_request('EventsRouter', 'query', [data])['result'] | |
def printEvents(out): | |
for e in out['events']: | |
#pp.pprint(e) | |
outState=e['eventState'] | |
if e['DeviceClass']: | |
outDeviceClass=e['DeviceClass'][0]['name'] | |
else: outDeviceClass=[] | |
outcount=e['count'] | |
outdevice=e['device']['text'] | |
if e['Location']: | |
outLocation=e['Location'][0]['name'] | |
else: outLocation=[] | |
outSystems=[] | |
for pos,val in enumerate(e['Systems']): | |
sy=str(e['Systems'][pos]['name']) | |
outSystems.append(sy) | |
outseverity=e['severity'] | |
outfirstTime=e['firstTime'] | |
outlastTime=e['lastTime'] | |
outsummary=e['summary'] | |
print '%s,%s,%s,%s,%s,%s,%s,%s,%s,%s' % (outState, outDeviceClass, outcount, outdevice, outLocation, outSystems, outseverity, outfirstTime, outlastTime, outsummary) | |
if __name__ == "__main__": | |
usage = 'python %prog --severity=severity --eventState=eventState --device=device --eventClass=eventClass --component=component --agent=agent --monitor=monitor --count=count --lastTime=lastTime --firstTime=firstTime --stateChange=stateChange --sort=lastTime --dir=DESC --archive=archive --limit=limit' | |
parser = OptionParser(usage) | |
parser.add_option("--severity", dest='severity', | |
help='severity comma-separated numeric values eg. severity=5,4 for Critical and Error') | |
parser.add_option("--eventState", dest='eventState', default='0,1', | |
help='eventState comma-separated numeric values eg. eventState=0,1 for New and Ack') | |
parser.add_option("--device", dest='device', | |
help='eg. --device=\'zen42.class.example.org\'') | |
parser.add_option("--eventClass", dest='eventClass', | |
help='eg. --eventClass=\'/Skills\'') | |
parser.add_option("--component", dest='component', | |
help='eg. --component=\'Test Component\'') | |
parser.add_option("--agent", dest='agent', | |
help='eg. --agent=\'zensyslog\'') | |
parser.add_option("--monitor", dest='monitor', | |
help='eg. --monitor=\'localhost\'') | |
parser.add_option("--count", dest='count', | |
help='numeric value eg. --count=3 or range --count 3,30') | |
parser.add_option("--lastTime", dest='lastTime', | |
help='eg. for a range separate start & end with / --lastTime=\'2012-09-07 07:57:33/2012-11-22 17:57:33\'') | |
parser.add_option("--firstTime", dest='firstTime', | |
help='eg. --firstTime=\'2012-11-22 17:57:33\'') | |
parser.add_option("--stateChange", dest='stateChange', | |
help='eg. --stateChange=\'2012-11-22 17:57:33\'') | |
parser.add_option("--sort", dest='sort', default='lastTime', | |
help='the key to sort on eg. --sort=\'lastTime\'') | |
parser.add_option("--dir", dest='dir', default='DESC', | |
help='the direction to sort eg. --dir=\'ASC\' or --dir=\'DESC\'') | |
parser.add_option("--archive", dest='archive', default=False, | |
help='include archived events as well as summary events. Default is False. eg. --archive=True ') | |
parser.add_option("--limit", dest='limit', default=1000, | |
help='Number of events to return. Default is 1000 for summary and 1000 for archive (if specified). Eg. --limit=500 ') | |
(options, args) = parser.parse_args() | |
# options is an object - we want the dictionary value of it | |
# Some of the options need a little munging... | |
option_dict = vars(options) | |
if option_dict['severity']: | |
option_dict['severity'] = option_dict['severity'].split(',') | |
if option_dict['eventState']: | |
option_dict['eventState'] = option_dict['eventState'].split(',') | |
# count can either be a number or a range (in either list or tuple format) | |
# (see $ZENHOME/Products/Zuul/facades/zepfacade.py - createEventFilter method ) | |
# but if this method gets a list it assumes there are 2 elements to the list. | |
# We may get a list with a single value so convert it to a number and the | |
# createEventFilter method can cope | |
if option_dict['count']: | |
option_dict['count'] = option_dict['count'].split(',') | |
if len(option_dict['count']) == 1: | |
option_dict['count'] = int(option_dict['count'][0]) | |
# option_dict includes the sort, dir, limit and archive keys (as we have defaulted them in optparse) | |
# These are not part of the filter string so we need to pop them out of the dictionary | |
# to use separately. | |
s = option_dict.pop('sort') | |
d = option_dict.pop('dir') | |
if option_dict['archive'] == 'True': | |
ar = True | |
else: | |
ar = False | |
a = option_dict.pop('archive') | |
l = option_dict.pop('limit') | |
# Need to check these keys for sanity | |
# and provide sensible defaults otherwise | |
dirlist=['ASC','DESC'] | |
if not d in dirlist: | |
d='DESC' | |
sortlist = ['severity', 'eventState', 'eventClass', 'firstTime', 'lastTime', | |
'stateChange', 'count', 'device', 'component', 'agent', 'monitor'] | |
if not s in sortlist: | |
s='lastTime' | |
#if type(a) != bool: | |
# a = False | |
if type(l) != str: | |
l = 1000 | |
else: | |
l=int(l) | |
#print 'options is %s \n' % (options) | |
#print 'option_dict is %s \n' % (option_dict) | |
events = getEventsWithJSON() | |
#filter['evid'] = '000c29d9-f87b-8389-11e2-347cddf7a720' | |
pp = pprint.PrettyPrinter(indent=4) | |
fields = ['eventState', 'DeviceClass', 'count', 'device', 'Location', 'Systems', 'severity', 'firstTime', 'lastTime', 'summary'] | |
print 'Summary events \n' | |
print 'eventState, DeviceClass, count, device, Location, Systems, severity, firstTime, lastTime, summary \n' | |
sumout = events.get_events(filter=option_dict, sort=s, dir=d, arch=False, lim=l) | |
#print 'sumout is %s \n' % (sumout) | |
#print 'Length of sumout is %s\n' % (len(sumout['events'])) | |
printEvents(sumout) | |
if l < sumout['totalCount']: | |
print '\n totalCount in Summary table is %d of which %d were selected as requested. asof is %s' % (sumout['totalCount'], l, sumout['asof']) | |
sumTotal = l | |
else: | |
print '\n totalCount in Summary table is %d and asof is %s' % (sumout['totalCount'], sumout['asof']) | |
sumTotal = sumout['totalCount'] | |
if ar: #want archive events as well as summary events | |
print '\n\nArchive events \n' | |
print 'eventState, DeviceClass, count, device, Location, Systems, severity, firstTime, lastTime, summary \n' | |
archout = events.get_events(filter=option_dict, sort=s, dir=d, arch=True, lim=l) | |
#print 'Length of archout is %s\n' % (len(archout['events'])) | |
printEvents(archout) | |
if l < archout['totalCount']: | |
print '\n totalCount in Archive table is %d of which %d were selected as requested. asof is %s' % (archout['totalCount'], l, archout['asof']) | |
print '\n\n Grand total of selected events is %d \n' % (l + sumTotal) | |
else: | |
print '\n totalCount in Archive table is %d and asof is %s' % (archout['totalCount'], archout['asof']) | |
print '\n\n Grand total of selected events is %d \n' % (sumTotal + archout['totalCount']) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment