summaryrefslogtreecommitdiffstats
path: root/roles/lib_zabbix/library/zbx_action.py
diff options
context:
space:
mode:
Diffstat (limited to 'roles/lib_zabbix/library/zbx_action.py')
-rw-r--r--roles/lib_zabbix/library/zbx_action.py690
1 files changed, 0 insertions, 690 deletions
diff --git a/roles/lib_zabbix/library/zbx_action.py b/roles/lib_zabbix/library/zbx_action.py
deleted file mode 100644
index 499084942..000000000
--- a/roles/lib_zabbix/library/zbx_action.py
+++ /dev/null
@@ -1,690 +0,0 @@
-#!/usr/bin/env python
-# vim: expandtab:tabstop=4:shiftwidth=4
-'''
- Ansible module for zabbix actions
-'''
-#
-# Zabbix action ansible module
-#
-#
-# Copyright 2015 Red Hat Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# This is in place because each module looks similar to each other.
-# These need duplicate code as their behavior is very similar
-# but different for each zabbix class.
-# pylint: disable=duplicate-code
-
-# pylint: disable=import-error
-from openshift_tools.zbxapi import ZabbixAPI, ZabbixConnection, ZabbixAPIError
-
-CUSTOM_SCRIPT_ACTION = '0'
-IPMI_ACTION = '1'
-SSH_ACTION = '2'
-TELNET_ACTION = '3'
-GLOBAL_SCRIPT_ACTION = '4'
-
-EXECUTE_ON_ZABBIX_AGENT = '0'
-EXECUTE_ON_ZABBIX_SERVER = '1'
-
-OPERATION_REMOTE_COMMAND = '1'
-
-def exists(content, key='result'):
- ''' Check if key exists in content or the size of content[key] > 0
- '''
- if not content.has_key(key):
- return False
-
- if not content[key]:
- return False
-
- return True
-
-def conditions_equal(zab_conditions, user_conditions):
- '''Compare two lists of conditions'''
- c_type = 'conditiontype'
- _op = 'operator'
- val = 'value'
- if len(user_conditions) != len(zab_conditions):
- return False
-
- for zab_cond, user_cond in zip(zab_conditions, user_conditions):
- if zab_cond[c_type] != str(user_cond[c_type]) or zab_cond[_op] != str(user_cond[_op]) or \
- zab_cond[val] != str(user_cond[val]):
- return False
-
- return True
-
-def filter_differences(zabbix_filters, user_filters):
- '''Determine the differences from user and zabbix for operations'''
- rval = {}
- for key, val in user_filters.items():
-
- if key == 'conditions':
- if not conditions_equal(zabbix_filters[key], val):
- rval[key] = val
-
- elif zabbix_filters[key] != str(val):
- rval[key] = val
-
- return rval
-
-def opconditions_diff(zab_val, user_val):
- ''' Report whether there are differences between opconditions on
- zabbix and opconditions supplied by user '''
-
- if len(zab_val) != len(user_val):
- return True
-
- for z_cond, u_cond in zip(zab_val, user_val):
- if not all([str(u_cond[op_key]) == z_cond[op_key] for op_key in \
- ['conditiontype', 'operator', 'value']]):
- return True
-
- return False
-
-def opmessage_diff(zab_val, user_val):
- ''' Report whether there are differences between opmessage on
- zabbix and opmessage supplied by user '''
-
- for op_msg_key, op_msg_val in user_val.items():
- if zab_val[op_msg_key] != str(op_msg_val):
- return True
-
- return False
-
-def opmessage_grp_diff(zab_val, user_val):
- ''' Report whether there are differences between opmessage_grp
- on zabbix and opmessage_grp supplied by user '''
-
- zab_grp_ids = set([ugrp['usrgrpid'] for ugrp in zab_val])
- usr_grp_ids = set([ugrp['usrgrpid'] for ugrp in user_val])
- if usr_grp_ids != zab_grp_ids:
- return True
-
- return False
-
-def opmessage_usr_diff(zab_val, user_val):
- ''' Report whether there are differences between opmessage_usr
- on zabbix and opmessage_usr supplied by user '''
-
- zab_usr_ids = set([usr['userid'] for usr in zab_val])
- usr_ids = set([usr['userid'] for usr in user_val])
- if usr_ids != zab_usr_ids:
- return True
-
- return False
-
-def opcommand_diff(zab_op_cmd, usr_op_cmd):
- ''' Check whether user-provided opcommand matches what's already
- stored in Zabbix '''
-
- for usr_op_cmd_key, usr_op_cmd_val in usr_op_cmd.items():
- if zab_op_cmd[usr_op_cmd_key] != str(usr_op_cmd_val):
- return True
- return False
-
-def host_in_zabbix(zab_hosts, usr_host):
- ''' Check whether a particular user host is already in the
- Zabbix list of hosts '''
-
- for usr_hst_key, usr_hst_val in usr_host.items():
- for zab_host in zab_hosts:
- if usr_hst_key in zab_host and \
- zab_host[usr_hst_key] == str(usr_hst_val):
- return True
-
- return False
-
-def hostlist_in_zabbix(zab_hosts, usr_hosts):
- ''' Check whether user-provided list of hosts are already in
- the Zabbix action '''
-
- if len(zab_hosts) != len(usr_hosts):
- return False
-
- for usr_host in usr_hosts:
- if not host_in_zabbix(zab_hosts, usr_host):
- return False
-
- return True
-
-# We are comparing two lists of dictionaries (the one stored on zabbix and the
-# one the user is providing). For each type of operation, determine whether there
-# is a difference between what is stored on zabbix and what the user is providing.
-# If there is a difference, we take the user-provided data for what needs to
-# be stored/updated into zabbix.
-def operation_differences(zabbix_ops, user_ops):
- '''Determine the differences from user and zabbix for operations'''
-
- # if they don't match, take the user options
- if len(zabbix_ops) != len(user_ops):
- return user_ops
-
- rval = {}
- for zab, user in zip(zabbix_ops, user_ops):
- for oper in user.keys():
- if oper == 'opconditions' and opconditions_diff(zab[oper], \
- user[oper]):
- rval[oper] = user[oper]
-
- elif oper == 'opmessage' and opmessage_diff(zab[oper], \
- user[oper]):
- rval[oper] = user[oper]
-
- elif oper == 'opmessage_grp' and opmessage_grp_diff(zab[oper], \
- user[oper]):
- rval[oper] = user[oper]
-
- elif oper == 'opmessage_usr' and opmessage_usr_diff(zab[oper], \
- user[oper]):
- rval[oper] = user[oper]
-
- elif oper == 'opcommand' and opcommand_diff(zab[oper], \
- user[oper]):
- rval[oper] = user[oper]
-
- # opcommand_grp can be treated just like opcommand_hst
- # as opcommand_grp[] is just a list of groups
- elif oper == 'opcommand_hst' or oper == 'opcommand_grp':
- if not hostlist_in_zabbix(zab[oper], user[oper]):
- rval[oper] = user[oper]
-
- # if it's any other type of operation than the ones tested above
- # just do a direct compare
- elif oper not in ['opconditions', 'opmessage', 'opmessage_grp',
- 'opmessage_usr', 'opcommand', 'opcommand_hst',
- 'opcommand_grp'] \
- and str(zab[oper]) != str(user[oper]):
- rval[oper] = user[oper]
-
- return rval
-
-def get_users(zapi, users):
- '''get the mediatype id from the mediatype name'''
- rval_users = []
-
- for user in users:
- content = zapi.get_content('user',
- 'get',
- {'filter': {'alias': user}})
- rval_users.append({'userid': content['result'][0]['userid']})
-
- return rval_users
-
-def get_user_groups(zapi, groups):
- '''get the mediatype id from the mediatype name'''
- user_groups = []
-
- for group in groups:
- content = zapi.get_content('usergroup',
- 'get',
- {'search': {'name': group}})
- for result in content['result']:
- user_groups.append({'usrgrpid': result['usrgrpid']})
-
- return user_groups
-
-def get_mediatype_id_by_name(zapi, m_name):
- '''get the mediatype id from the mediatype name'''
- content = zapi.get_content('mediatype',
- 'get',
- {'filter': {'description': m_name}})
-
- return content['result'][0]['mediatypeid']
-
-def get_priority(priority):
- ''' determine priority
- '''
- prior = 0
- if 'info' in priority:
- prior = 1
- elif 'warn' in priority:
- prior = 2
- elif 'avg' == priority or 'ave' in priority:
- prior = 3
- elif 'high' in priority:
- prior = 4
- elif 'dis' in priority:
- prior = 5
-
- return prior
-
-def get_event_source(from_src):
- '''Translate even str into value'''
- choices = ['trigger', 'discovery', 'auto', 'internal']
- rval = 0
- try:
- rval = choices.index(from_src)
- except ValueError as _:
- ZabbixAPIError('Value not found for event source [%s]' % from_src)
-
- return rval
-
-def get_status(inc_status):
- '''determine status for action'''
- rval = 1
- if inc_status == 'enabled':
- rval = 0
-
- return rval
-
-def get_condition_operator(inc_operator):
- ''' determine the condition operator'''
- vals = {'=': 0,
- '<>': 1,
- 'like': 2,
- 'not like': 3,
- 'in': 4,
- '>=': 5,
- '<=': 6,
- 'not in': 7,
- }
-
- return vals[inc_operator]
-
-def get_host_id_by_name(zapi, host_name):
- '''Get host id by name'''
- content = zapi.get_content('host',
- 'get',
- {'filter': {'name': host_name}})
-
- return content['result'][0]['hostid']
-
-def get_trigger_value(inc_trigger):
- '''determine the proper trigger value'''
- rval = 1
- if inc_trigger == 'PROBLEM':
- rval = 1
- else:
- rval = 0
-
- return rval
-
-def get_template_id_by_name(zapi, t_name):
- '''get the template id by name'''
- content = zapi.get_content('template',
- 'get',
- {'filter': {'host': t_name}})
-
- return content['result'][0]['templateid']
-
-
-def get_host_group_id_by_name(zapi, hg_name):
- '''Get hostgroup id by name'''
- content = zapi.get_content('hostgroup',
- 'get',
- {'filter': {'name': hg_name}})
-
- return content['result'][0]['groupid']
-
-def get_condition_type(event_source, inc_condition):
- '''determine the condition type'''
- c_types = {}
- if event_source == 'trigger':
- c_types = {'host group': 0,
- 'host': 1,
- 'trigger': 2,
- 'trigger name': 3,
- 'trigger severity': 4,
- 'trigger value': 5,
- 'time period': 6,
- 'host template': 13,
- 'application': 15,
- 'maintenance status': 16,
- }
-
- elif event_source == 'discovery':
- c_types = {'host IP': 7,
- 'discovered service type': 8,
- 'discovered service port': 9,
- 'discovery status': 10,
- 'uptime or downtime duration': 11,
- 'received value': 12,
- 'discovery rule': 18,
- 'discovery check': 19,
- 'proxy': 20,
- 'discovery object': 21,
- }
-
- elif event_source == 'auto':
- c_types = {'proxy': 20,
- 'host name': 22,
- 'host metadata': 24,
- }
-
- elif event_source == 'internal':
- c_types = {'host group': 0,
- 'host': 1,
- 'host template': 13,
- 'application': 15,
- 'event type': 23,
- }
- else:
- raise ZabbixAPIError('Unkown event source %s' % event_source)
-
- return c_types[inc_condition]
-
-def get_operation_type(inc_operation):
- ''' determine the correct operation type'''
- o_types = {'send message': 0,
- 'remote command': OPERATION_REMOTE_COMMAND,
- 'add host': 2,
- 'remove host': 3,
- 'add to host group': 4,
- 'remove from host group': 5,
- 'link to template': 6,
- 'unlink from template': 7,
- 'enable host': 8,
- 'disable host': 9,
- }
-
- return o_types[inc_operation]
-
-def get_opcommand_type(opcommand_type):
- ''' determine the opcommand type '''
- oc_types = {'custom script': CUSTOM_SCRIPT_ACTION,
- 'IPMI': IPMI_ACTION,
- 'SSH': SSH_ACTION,
- 'Telnet': TELNET_ACTION,
- 'global script': GLOBAL_SCRIPT_ACTION,
- }
-
- return oc_types[opcommand_type]
-
-def get_execute_on(execute_on):
- ''' determine the execution target '''
- e_types = {'zabbix agent': EXECUTE_ON_ZABBIX_AGENT,
- 'zabbix server': EXECUTE_ON_ZABBIX_SERVER,
- }
-
- return e_types[execute_on]
-
-def action_remote_command(ansible_module, zapi, operation):
- ''' Process remote command type of actions '''
-
- if 'type' not in operation['opcommand']:
- ansible_module.exit_json(failed=True, changed=False, state='unknown',
- results="No Operation Type provided")
-
- operation['opcommand']['type'] = get_opcommand_type(operation['opcommand']['type'])
-
- if operation['opcommand']['type'] == CUSTOM_SCRIPT_ACTION:
-
- if 'execute_on' in operation['opcommand']:
- operation['opcommand']['execute_on'] = get_execute_on(operation['opcommand']['execute_on'])
-
- # custom script still requires the target hosts/groups to be set
- operation['opcommand_hst'] = []
- operation['opcommand_grp'] = []
- for usr_host in operation['target_hosts']:
- if usr_host['target_type'] == 'zabbix server':
- # 0 = target host local/current host
- operation['opcommand_hst'].append({'hostid': 0})
- elif usr_host['target_type'] == 'group':
- group_name = usr_host['target']
- gid = get_host_group_id_by_name(zapi, group_name)
- operation['opcommand_grp'].append({'groupid': gid})
- elif usr_host['target_type'] == 'host':
- host_name = usr_host['target']
- hid = get_host_id_by_name(zapi, host_name)
- operation['opcommand_hst'].append({'hostid': hid})
-
- # 'target_hosts' is just to make it easier to build zbx_actions
- # not part of ZabbixAPI
- del operation['target_hosts']
- else:
- ansible_module.exit_json(failed=True, changed=False, state='unknown',
- results="Unsupported remote command type")
-
-
-def get_action_operations(ansible_module, zapi, inc_operations):
- '''Convert the operations into syntax for api'''
- for operation in inc_operations:
- operation['operationtype'] = get_operation_type(operation['operationtype'])
- if operation['operationtype'] == 0: # send message. Need to fix the
- operation['opmessage']['mediatypeid'] = \
- get_mediatype_id_by_name(zapi, operation['opmessage']['mediatypeid'])
- operation['opmessage_grp'] = get_user_groups(zapi, operation.get('opmessage_grp', []))
- operation['opmessage_usr'] = get_users(zapi, operation.get('opmessage_usr', []))
- if operation['opmessage']['default_msg']:
- operation['opmessage']['default_msg'] = 1
- else:
- operation['opmessage']['default_msg'] = 0
-
- elif operation['operationtype'] == OPERATION_REMOTE_COMMAND:
- action_remote_command(ansible_module, zapi, operation)
-
- # Handle Operation conditions:
- # Currently there is only 1 available which
- # is 'event acknowledged'. In the future
- # if there are any added we will need to pass this
- # option to a function and return the correct conditiontype
- if operation.has_key('opconditions'):
- for condition in operation['opconditions']:
- if condition['conditiontype'] == 'event acknowledged':
- condition['conditiontype'] = 14
-
- if condition['operator'] == '=':
- condition['operator'] = 0
-
- if condition['value'] == 'acknowledged':
- condition['value'] = 1
- else:
- condition['value'] = 0
-
-
- return inc_operations
-
-def get_operation_evaltype(inc_type):
- '''get the operation evaltype'''
- rval = 0
- if inc_type == 'and/or':
- rval = 0
- elif inc_type == 'and':
- rval = 1
- elif inc_type == 'or':
- rval = 2
- elif inc_type == 'custom':
- rval = 3
-
- return rval
-
-def get_action_conditions(zapi, event_source, inc_conditions):
- '''Convert the conditions into syntax for api'''
-
- calc_type = inc_conditions.pop('calculation_type')
- inc_conditions['evaltype'] = get_operation_evaltype(calc_type)
- for cond in inc_conditions['conditions']:
-
- cond['operator'] = get_condition_operator(cond['operator'])
- # Based on conditiontype we need to set the proper value
- # e.g. conditiontype = hostgroup then the value needs to be a hostgroup id
- # e.g. conditiontype = host the value needs to be a host id
- cond['conditiontype'] = get_condition_type(event_source, cond['conditiontype'])
- if cond['conditiontype'] == 0:
- cond['value'] = get_host_group_id_by_name(zapi, cond['value'])
- elif cond['conditiontype'] == 1:
- cond['value'] = get_host_id_by_name(zapi, cond['value'])
- elif cond['conditiontype'] == 4:
- cond['value'] = get_priority(cond['value'])
-
- elif cond['conditiontype'] == 5:
- cond['value'] = get_trigger_value(cond['value'])
- elif cond['conditiontype'] == 13:
- cond['value'] = get_template_id_by_name(zapi, cond['value'])
- elif cond['conditiontype'] == 16:
- cond['value'] = ''
-
- return inc_conditions
-
-
-def get_send_recovery(send_recovery):
- '''Get the integer value'''
- rval = 0
- if send_recovery:
- rval = 1
-
- return rval
-
-# The branches are needed for CRUD and error handling
-# pylint: disable=too-many-branches
-def main():
- '''
- ansible zabbix module for zbx_item
- '''
-
-
- module = AnsibleModule(
- argument_spec=dict(
- zbx_server=dict(default='https://localhost/zabbix/api_jsonrpc.php', type='str'),
- zbx_user=dict(default=os.environ.get('ZABBIX_USER', None), type='str'),
- zbx_password=dict(default=os.environ.get('ZABBIX_PASSWORD', None), type='str'),
- zbx_debug=dict(default=False, type='bool'),
-
- name=dict(default=None, type='str'),
- event_source=dict(default='trigger', choices=['trigger', 'discovery', 'auto', 'internal'], type='str'),
- action_subject=dict(default="{TRIGGER.NAME}: {TRIGGER.STATUS}", type='str'),
- action_message=dict(default="{TRIGGER.NAME}: {TRIGGER.STATUS}\r\n" +
- "Last value: {ITEM.LASTVALUE}\r\n\r\n{TRIGGER.URL}", type='str'),
- reply_subject=dict(default="{TRIGGER.NAME}: {TRIGGER.STATUS}", type='str'),
- reply_message=dict(default="Trigger: {TRIGGER.NAME}\r\nTrigger status: {TRIGGER.STATUS}\r\n" +
- "Trigger severity: {TRIGGER.SEVERITY}\r\nTrigger URL: {TRIGGER.URL}\r\n\r\n" +
- "Item values:\r\n\r\n1. {ITEM.NAME1} ({HOST.NAME1}:{ITEM.KEY1}): " +
- "{ITEM.VALUE1}\r\n2. {ITEM.NAME2} ({HOST.NAME2}:{ITEM.KEY2}): " +
- "{ITEM.VALUE2}\r\n3. {ITEM.NAME3} ({HOST.NAME3}:{ITEM.KEY3}): " +
- "{ITEM.VALUE3}", type='str'),
- send_recovery=dict(default=False, type='bool'),
- status=dict(default=None, type='str'),
- escalation_time=dict(default=60, type='int'),
- conditions_filter=dict(default=None, type='dict'),
- operations=dict(default=None, type='list'),
- state=dict(default='present', type='str'),
- ),
- #supports_check_mode=True
- )
-
- zapi = ZabbixAPI(ZabbixConnection(module.params['zbx_server'],
- module.params['zbx_user'],
- module.params['zbx_password'],
- module.params['zbx_debug']))
-
- #Set the instance and the template for the rest of the calls
- zbx_class_name = 'action'
- state = module.params['state']
-
- content = zapi.get_content(zbx_class_name,
- 'get',
- {'search': {'name': module.params['name']},
- 'selectFilter': 'extend',
- 'selectOperations': 'extend',
- })
-
- #******#
- # GET
- #******#
- if state == 'list':
- module.exit_json(changed=False, results=content['result'], state="list")
-
- #******#
- # DELETE
- #******#
- if state == 'absent':
- if not exists(content):
- module.exit_json(changed=False, state="absent")
-
- content = zapi.get_content(zbx_class_name, 'delete', [content['result'][0]['actionid']])
- module.exit_json(changed=True, results=content['result'], state="absent")
-
- # Create and Update
- if state == 'present':
-
- conditions = get_action_conditions(zapi, module.params['event_source'], module.params['conditions_filter'])
- operations = get_action_operations(module, zapi,
- module.params['operations'])
- params = {'name': module.params['name'],
- 'esc_period': module.params['escalation_time'],
- 'eventsource': get_event_source(module.params['event_source']),
- 'status': get_status(module.params['status']),
- 'def_shortdata': module.params['action_subject'],
- 'def_longdata': module.params['action_message'],
- 'r_shortdata': module.params['reply_subject'],
- 'r_longdata': module.params['reply_message'],
- 'recovery_msg': get_send_recovery(module.params['send_recovery']),
- 'filter': conditions,
- 'operations': operations,
- }
-
- # Remove any None valued params
- _ = [params.pop(key, None) for key in params.keys() if params[key] is None]
-
- #******#
- # CREATE
- #******#
- if not exists(content):
- content = zapi.get_content(zbx_class_name, 'create', params)
-
- if content.has_key('error'):
- module.exit_json(failed=True, changed=True, results=content['error'], state="present")
-
- module.exit_json(changed=True, results=content['result'], state='present')
-
-
- ########
- # UPDATE
- ########
- _ = params.pop('hostid', None)
- differences = {}
- zab_results = content['result'][0]
- for key, value in params.items():
-
- if key == 'operations':
- ops = operation_differences(zab_results[key], value)
- if ops:
- differences[key] = ops
-
- elif key == 'filter':
- filters = filter_differences(zab_results[key], value)
- if filters:
- differences[key] = filters
-
- elif zab_results[key] != value and zab_results[key] != str(value):
- differences[key] = value
-
- if not differences:
- module.exit_json(changed=False, results=zab_results, state="present")
-
- # We have differences and need to update.
- # action update requires an id, filters, and operations
- differences['actionid'] = zab_results['actionid']
- differences['operations'] = params['operations']
- differences['filter'] = params['filter']
- content = zapi.get_content(zbx_class_name, 'update', differences)
-
- if content.has_key('error'):
- module.exit_json(failed=True, changed=False, results=content['error'], state="present")
-
- module.exit_json(changed=True, results=content['result'], state="present")
-
- module.exit_json(failed=True,
- changed=False,
- results='Unknown state passed. %s' % state,
- state="unknown")
-
-# pylint: disable=redefined-builtin, unused-wildcard-import, wildcard-import, locally-disabled
-# import module snippets. This are required
-from ansible.module_utils.basic import *
-
-main()