Skip to content

Instantly share code, notes, and snippets.

@jupemara
Last active August 29, 2015 14:06
Show Gist options
  • Save jupemara/1a2aaf0d4a13bf76ce89 to your computer and use it in GitHub Desktop.
Save jupemara/1a2aaf0d4a13bf76ce89 to your computer and use it in GitHub Desktop.
This script change zabbix trigger priority
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Change trigger priority
that occurs more than specified counts in the specified time period.
"""
import json
import logging
import optparse
import sys
import time
import urllib2
DEFAULT = {
'zabbix_server_schema': 'http',
'zabbix_server_host': '127.0.0.1',
'zabbix_server_port': '80',
'zabbix_api_username': 'Admin',
'zabbix_api_password': 'zabbix',
'zabbix_api_userid': 1,
'log_level': 'INFO',
'period': '30m',
'in_threshold_count': 8,
'out_threshold_count': 2,
'target_trigger_name': None,
'source_priority': 'Average',
'target_priority': 'Not classified',
'exclude_string': 'Trigger status: OK'
}
ZABBIX_PRIORITIES = {
'Not classified': 0,
'Information': 1,
'Warning': 2,
'Average': 3,
'High': 4,
'Disaster': 5
}
def get_args():
usage = (
'Change trigger priority that occurs more '
'than specified counts in the specified time period.'
)
parser = optparse.OptionParser(usage=usage)
parser.add_option(
'--zabbix-server-schema', '-S',
type='string', default=DEFAULT['zabbix_server_schema'],
dest='zabbix_server_schema',
help='Schema to access to zabbix server API. e.g: http, https.'
)
parser.add_option(
'--zabbix-server-host', '-H',
type='string', default=DEFAULT['zabbix_server_host'],
dest='zabbix_server_host',
help='Zabbix server hostname or IP address.'
)
parser.add_option(
'--zabbix-server-port', '-P',
type='string', default=DEFAULT['zabbix_server_port'],
dest='zabbix_server_port',
help='Zabbix server API port number.'
)
parser.add_option(
'--zabbix-api-username', '-u',
type='string', default=DEFAULT['zabbix_api_username'],
dest='zabbix_api_username',
help='Zabbix API username.'
)
parser.add_option(
'--zabbix-api-password', '-p',
type='string', default=DEFAULT['zabbix_api_password'],
dest='zabbix_api_password',
help='Zabbix API password.'
),
parser.add_option(
'--zabbix-api-userid', '-i',
type='string', default=DEFAULT['zabbix_api_userid'],
dest='zabbix_api_userid',
help='Zabbix API user id.'
)
parser.add_option(
'--log-level', '-l',
type='choice', default=DEFAULT['log_level'],
dest='log_level',
choices=[
'DEBUG',
'INFO',
'WARNING',
'ERROR',
'CRITICAL'
],
help='Script log level.'
)
parser.add_option(
'--period', '-x',
type='string', default=DEFAULT['period'],
dest='period',
help='Time period. You can use "d", "h", "m" and "s" as time unit.'
)
parser.add_option(
'--in-threshold-count', '-c',
type='int', default=DEFAULT['in_threshold_count'],
dest='in_threshold_count',
help='Alert count in threshold per specified time period.'
)
parser.add_option(
'--out-threshold-count', '-C',
type='int', default=DEFAULT['out_threshold_count'],
dest='out_threshold_count',
help='Alert count out threshold per specified time period.'
)
parser.add_option(
'--target-trigger-name', '-n',
type='string', default=DEFAULT['target_trigger_name'],
dest='target_trigger_name',
help='Target trigger full name. This option works in perfect match.'
)
parser.add_option(
'--source-priority', '-s',
type='choice', default=DEFAULT['source_priority'],
dest='source_priority',
choices=ZABBIX_PRIORITIES.keys(),
help='If alert counts is not over threshold, script set this value.'
)
parser.add_option(
'--target-priority', '-t',
type='choice', default=DEFAULT['target_priority'],
dest='target_priority',
choices=ZABBIX_PRIORITIES.keys(),
help='If alert counts is over threshold, script set this value.'
)
parser.add_option(
'--exclude-string', '-e',
type='string', default=DEFAULT['exclude_string'],
dest='exclude_string',
help=(
'If specified string is included in alert message,'
' script doesn\'t count as alert count.'
)
)
return parser.parse_args()[0]
def period2seconds(period):
"""
convert time period to seconds.
e.x:
1d = 86400
1h = 3600
1m = 60
1s = 1
"""
unit_map = {
'd': 86400,
'h': 3600,
'm': 60,
's': 1
}
unit = period[-1]
value = period[0:-1]
try:
unit = unit.lower()
logging.debug(
'Current unit is "{0}"'.format(unit)
)
result = int(value) * unit_map[unit]
logging.debug(
'Converted value is "{0}" seconds'.format(result)
)
except Exception as exception:
raise ZabbixChangePriorityScriptException(
'Invalid specification time period {0}.'.format(period)
)
return result
def set_log_level(log_level='DEBUG'):
logging.basicConfig(
format='[%(levelname)s] %(message)s',
level=getattr(logging, log_level)
)
class ZabbixChangePriorityScriptException(BaseException):
def __init__(self, message):
super(ZabbixChangePriorityScriptException, self).__init__(message)
class ZabbixAPI(object):
headers = {'Content-type': 'application/json'}
def __init__(self,
zabbix_server_schema=DEFAULT['zabbix_server_schema'],
zabbix_server_host=DEFAULT['zabbix_server_host'],
zabbix_server_port=DEFAULT['zabbix_server_port'],
zabbix_api_username=DEFAULT['zabbix_api_username'],
zabbix_api_password=DEFAULT['zabbix_api_password'],
zabbix_api_userid=DEFAULT['zabbix_api_userid']
):
self.api_userid = zabbix_api_userid
self.url = (
'{schema}://{host}:{port}/zabbix/api_jsonrpc.php'
''.format(
schema=zabbix_server_schema,
host=zabbix_server_host,
port=zabbix_server_port
)
)
self.token = None
response = self.api_call(
method='user.login',
params={
'user': zabbix_api_username,
'password': zabbix_api_password
}
)
if 'result' in response:
self.token = response['result']
else:
raise ZabbixChangePriorityScriptException(
'{0}'.format(response['error']['data'])
)
def api_call(self, method, params):
data = {
'auth': self.token,
'method': method,
'id': self.api_userid,
'params': params,
'jsonrpc': 2.0
}
request = urllib2.Request(
url=self.url,
data=json.dumps(data),
headers=self.headers
)
response = json.loads(urllib2.urlopen(request).next())
return response
def get_triggerids(trigger_name, zabbix_api, templated=False):
response = zabbix_api.api_call(
method='trigger.get',
params={
'search': {
'description': trigger_name
},
'output': ['triggerids'],
'templated': templated
}
)
if not 'result' in response:
raise ZabbixChangePriorityScriptException(
'Maybe "{0}" trigger does not exist.'.format(trigger_name)
)
logging.debug(
'Raw get_triggerids() response is {0}.'.format(response)
)
result = [
entry['triggerid'] for entry in response['result']
]
logging.debug(
'Get trigger ids are {0}'.format(result)
)
return result
def get_trigger_priority(triggerids, zabbix_api):
response = zabbix_api.api_call(
method='trigger.get',
params={
'triggerids': triggerids,
'output': ['priority'],
'templated': True
}
)
if not 'result' in response:
raise ZabbixChangePriorityScriptException(
'Maybe "{0}" trigger does not exist.'.format(triggerids)
)
else:
result_len = len(response['result'])
if result_len <= 0:
raise ZabbixChangePriorityScriptException(
'Maybe "{0}" trigger does not exist.'.format(triggerids)
)
elif result_len > 1:
raise ZabbixChangePriorityScriptException(
'An error occurred. Returned trigger item is Too many.'
)
logging.debug(
'Raw get_trigger_priority() response is {0}.'.format(response)
)
result = [
entry['priority'] for entry in response['result']
][0]
logging.debug(
'Get priority is {0}.'.format(result)
)
return result
def get_alert_count(triggerids, time_from, exclude_string, zabbix_api):
triggerids = [
int(entry) for entry in triggerids
]
response = zabbix_api.api_call(
method='alert.get',
params={
'objectids': triggerids,
'time_from': time_from,
'output': 'extend'
}
)
if not 'result' in response:
raise ZabbixChangePriorityScriptException(
'An error occurred. API response doesn\'t have "result" key.'
)
logging.debug(
'Raw get_alert_count() response is {0}.'.format(response)
)
alert_count = dict()
for entry in response['result']:
message = entry.get('message')
userid = entry.get('userid')
if message is not None and userid is not None:
if not exclude_string in entry['message']:
if not userid in alert_count:
alert_count[userid] = 1
else:
alert_count[userid] += 1
else:
logging.debug(
'"{0}" is included in "{1}"'
''.format(
exclude_string,
message
)
)
elif message is None and userid is None:
logging.warn(
(
'Both "message" and "userid" keys does not exist in {0}'
''.format(entry)
)
)
elif message is None:
logging.warn(
'"message" key does not exist in {0}'.format(entry)
)
elif userid is None:
logging.warn(
'"userid" key does not exist in {0}'.format(entry)
)
logging.info(
'Whole alerts count is {0}'.format(len(response['result']))
)
if not len(alert_count.values()):
result = 0
else:
result = max(alert_count.values())
logging.info(
'Alert count of specified trigger name is {0}.'.format(result)
)
return result
def set_priority(triggerid, priority, zabbix_api):
response = zabbix_api.api_call(
method='trigger.update',
params={
'triggerid': triggerid,
'priority': priority
}
)
if 'result' in response:
logging.warn(
(
'Succeed to set priority "{0}" to {1}.'
''.format(
priority,
triggerid
)
)
)
else:
logging.error(
(
'Failed to set priority "{0}" to {1}.'
''.format(
priority,
triggerid
)
)
)
def validate_options(options):
if options.target_trigger_name is None:
raise ZabbixChangePriorityScriptException(
'"--target-trigger-name" options is required.'
)
def main():
try:
options = get_args()
set_log_level(options.log_level)
zabbix_api = ZabbixAPI(
zabbix_server_schema=options.zabbix_server_schema,
zabbix_server_host=options.zabbix_server_host,
zabbix_server_port=options.zabbix_server_port,
zabbix_api_username=options.zabbix_api_username,
zabbix_api_password=options.zabbix_api_password,
zabbix_api_userid=options.zabbix_api_userid
)
validate_options(options)
triggerids = get_triggerids(
trigger_name=options.target_trigger_name,
zabbix_api=zabbix_api,
templated=False
)
templated_triggerid = get_triggerids(
trigger_name=options.target_trigger_name,
zabbix_api=zabbix_api,
templated=True
)[0]
current_priority = get_trigger_priority(
templated_triggerid,
zabbix_api=zabbix_api
)
seconds_period = int(time.time()) - period2seconds(options.period)
alert_count = get_alert_count(
triggerids=triggerids,
time_from=seconds_period,
exclude_string=options.exclude_string,
zabbix_api=zabbix_api
)
if alert_count >= options.in_threshold_count:
if (
int(current_priority) !=
int(ZABBIX_PRIORITIES[options.target_priority])
):
set_priority(
triggerid=templated_triggerid,
priority=int(ZABBIX_PRIORITIES[options.target_priority]),
zabbix_api=zabbix_api
)
elif alert_count <= options.out_threshold_count :
if (
int(current_priority) !=
int(ZABBIX_PRIORITIES[options.source_priority])
):
set_priority(
triggerid=templated_triggerid,
priority=int(ZABBIX_PRIORITIES[options.source_priority]),
zabbix_api=zabbix_api
)
except ZabbixChangePriorityScriptException as exception:
logging.error(exception.__str__())
sys.exit(1)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment