Last active
August 29, 2015 14:06
-
-
Save jupemara/1a2aaf0d4a13bf76ce89 to your computer and use it in GitHub Desktop.
This script change zabbix trigger priority
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 | |
# -*- 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