From 693be4802c2b3886b82681c5c1666b9f13d9ca36 Mon Sep 17 00:00:00 2001 From: Kenny Woodson Date: Fri, 21 Aug 2015 17:44:30 -0400 Subject: Updates for zbx ans module --- roles/lib_zabbix/library/zbx_itemprototype.py | 241 ++++++++++++++++++++++++++ 1 file changed, 241 insertions(+) create mode 100644 roles/lib_zabbix/library/zbx_itemprototype.py (limited to 'roles/lib_zabbix/library/zbx_itemprototype.py') diff --git a/roles/lib_zabbix/library/zbx_itemprototype.py b/roles/lib_zabbix/library/zbx_itemprototype.py new file mode 100644 index 000000000..47100f613 --- /dev/null +++ b/roles/lib_zabbix/library/zbx_itemprototype.py @@ -0,0 +1,241 @@ +#!/usr/bin/env python +''' +Zabbix discovery rule ansible module +''' +# vim: expandtab:tabstop=4:shiftwidth=4 +# +# 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.monitoring.zbxapi import ZabbixAPI, ZabbixConnection + +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 get_rule_id(zapi, discoveryrule_name): + '''get a discoveryrule by name + ''' + content = zapi.get_content('discoveryrule', + 'get', + {'search': {'name': discoveryrule_name}, + 'output': 'extend', + }) + if not content['result']: + return None + return content['result'][0]['itemid'] + +def get_template(zapi, template_name): + '''get a template by name + ''' + content = zapi.get_content('template', + 'get', + {'search': {'host': template_name}, + 'output': 'extend', + 'selectInterfaces': 'interfaceid', + }) + if not content['result']: + return None + return content['result'][0] + +def get_type(ztype): + ''' + Determine which type of discoverrule this is + ''' + _types = {'agent': 0, + 'SNMPv1': 1, + 'trapper': 2, + 'simple': 3, + 'SNMPv2': 4, + 'internal': 5, + 'SNMPv3': 6, + 'active': 7, + 'aggregate': 8, + 'external': 10, + 'database monitor': 11, + 'ipmi': 12, + 'ssh': 13, + 'telnet': 14, + 'calculated': 15, + 'JMX': 16, + } + + for typ in _types.keys(): + if ztype in typ or ztype == typ: + _vtype = _types[typ] + break + else: + _vtype = 2 + + return _vtype + +def get_value_type(value_type): + ''' + Possible values: + 0 - numeric float; + 1 - character; + 2 - log; + 3 - numeric unsigned; + 4 - text + ''' + vtype = 0 + if 'int' in value_type: + vtype = 3 + elif 'char' in value_type: + vtype = 1 + elif 'str' in value_type: + vtype = 4 + + return vtype + +def get_status(status): + ''' Determine status + ''' + _status = 0 + if status == 'disabled': + _status = 1 + elif status == 'unsupported': + _status = 3 + + return _status + +def get_app_ids(zapi, application_names): + ''' get application ids from names + ''' + app_ids = [] + for app_name in application_names: + content = zapi.get_content('application', 'get', {'search': {'name': app_name}}) + if content.has_key('result'): + app_ids.append(content['result'][0]['applicationid']) + return app_ids + +def main(): + ''' + Ansible module for zabbix discovery rules + ''' + + module = AnsibleModule( + argument_spec=dict( + zbx_server=dict(default='https://localhost/zabbix/api_jsonrpc.php', type='str'), + zbx_user=dict(default=os.environ['ZABBIX_USER'], type='str'), + zbx_password=dict(default=os.environ['ZABBIX_PASSWORD'], type='str'), + zbx_debug=dict(default=False, type='bool'), + name=dict(default=None, type='str'), + key=dict(default=None, type='str'), + interfaceid=dict(default=None, type='int'), + ztype=dict(default='trapper', type='str'), + value_type=dict(default='float', type='str'), + delay=dict(default=60, type='int'), + lifetime=dict(default=30, type='int'), + template_name=dict(default=[], type='list'), + state=dict(default='present', type='str'), + status=dict(default='enabled', type='str'), + discoveryrule_name=dict(default=None, type='str'), + applications=dict(default=[], type='list'), + ), + #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 = 'itemprototype' + idname = "itemid" + dname = module.params['name'] + state = module.params['state'] + + # selectInterfaces doesn't appear to be working but is needed. + content = zapi.get_content(zbx_class_name, + 'get', + {'search': {'name': dname}, + 'selectApplications': 'applicationid', + 'selectDiscoveryRule': 'itemid', + #'selectDhosts': 'dhostid', + }) + if state == 'list': + module.exit_json(changed=False, results=content['result'], state="list") + + 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][idname]]) + module.exit_json(changed=True, results=content['result'], state="absent") + + if state == 'present': + template = get_template(zapi, module.params['template_name']) + params = {'name': dname, + 'key_': module.params['key'], + 'hostid': template['templateid'], + 'interfaceid': module.params['interfaceid'], + 'ruleid': get_rule_id(zapi, module.params['discoveryrule_name']), + 'type': get_type(module.params['ztype']), + 'value_type': get_value_type(module.params['value_type']), + 'applications': get_app_ids(zapi, module.params['applications']), + } + if params['type'] in [2, 5, 7, 8, 11, 15]: + params.pop('interfaceid') + + if not exists(content): + # if we didn't find it, create it + content = zapi.get_content(zbx_class_name, 'create', params) + module.exit_json(changed=True, results=content['result'], state='present') + # already exists, we need to update it + # let's compare properties + differences = {} + zab_results = content['result'][0] + for key, value in params.items(): + + if key == 'ruleid': + if value != zab_results['discoveryRule']['itemid']: + differences[key] = value + + 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 + differences[idname] = zab_results[idname] + content = zapi.get_content(zbx_class_name, 'update', differences) + 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() -- cgit v1.2.3 From e8d71b6ed7421644a765564c85ca3ee32182fed2 Mon Sep 17 00:00:00 2001 From: Kenny Woodson Date: Thu, 27 Aug 2015 17:02:34 -0400 Subject: Fixed env var defaults. --- roles/lib_zabbix/library/zbx_itemprototype.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'roles/lib_zabbix/library/zbx_itemprototype.py') diff --git a/roles/lib_zabbix/library/zbx_itemprototype.py b/roles/lib_zabbix/library/zbx_itemprototype.py index 47100f613..24f85710d 100644 --- a/roles/lib_zabbix/library/zbx_itemprototype.py +++ b/roles/lib_zabbix/library/zbx_itemprototype.py @@ -142,8 +142,8 @@ def main(): module = AnsibleModule( argument_spec=dict( zbx_server=dict(default='https://localhost/zabbix/api_jsonrpc.php', type='str'), - zbx_user=dict(default=os.environ['ZABBIX_USER'], type='str'), - zbx_password=dict(default=os.environ['ZABBIX_PASSWORD'], 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'), key=dict(default=None, type='str'), -- cgit v1.2.3 From b800a153702168419d93ca82c8fa28f009bb64be Mon Sep 17 00:00:00 2001 From: Kenny Woodson Date: Tue, 22 Sep 2015 14:57:37 -0400 Subject: Fixed a few bugs and added support for prototypes and discoveryrules. --- roles/lib_zabbix/library/zbx_itemprototype.py | 56 +++++++++++++++++++++------ 1 file changed, 44 insertions(+), 12 deletions(-) (limited to 'roles/lib_zabbix/library/zbx_itemprototype.py') diff --git a/roles/lib_zabbix/library/zbx_itemprototype.py b/roles/lib_zabbix/library/zbx_itemprototype.py index 24f85710d..b93b7729e 100644 --- a/roles/lib_zabbix/library/zbx_itemprototype.py +++ b/roles/lib_zabbix/library/zbx_itemprototype.py @@ -38,13 +38,14 @@ def exists(content, key='result'): return True -def get_rule_id(zapi, discoveryrule_name): +def get_rule_id(zapi, discoveryrule_name, templateid): '''get a discoveryrule by name ''' content = zapi.get_content('discoveryrule', 'get', {'search': {'name': discoveryrule_name}, 'output': 'extend', + 'templateids': templateid, }) if not content['result']: return None @@ -53,6 +54,9 @@ def get_rule_id(zapi, discoveryrule_name): def get_template(zapi, template_name): '''get a template by name ''' + if not template_name: + return None + content = zapi.get_content('template', 'get', {'search': {'host': template_name}, @@ -134,6 +138,7 @@ def get_app_ids(zapi, application_names): app_ids.append(content['result'][0]['applicationid']) return app_ids +# pylint: disable=too-many-branches def main(): ''' Ansible module for zabbix discovery rules @@ -152,10 +157,10 @@ def main(): value_type=dict(default='float', type='str'), delay=dict(default=60, type='int'), lifetime=dict(default=30, type='int'), - template_name=dict(default=[], type='list'), + template_name=dict(default=None, required=True, type='str'), state=dict(default='present', type='str'), status=dict(default='enabled', type='str'), - discoveryrule_name=dict(default=None, type='str'), + discoveryrule_name=dict(default=None, required=True, type='str'), applications=dict(default=[], type='list'), ), #supports_check_mode=True @@ -169,20 +174,26 @@ def main(): #Set the instance and the template for the rest of the calls zbx_class_name = 'itemprototype' idname = "itemid" - dname = module.params['name'] state = module.params['state'] + template = get_template(zapi, module.params['template_name']) # selectInterfaces doesn't appear to be working but is needed. content = zapi.get_content(zbx_class_name, 'get', - {'search': {'name': dname}, + {'search': {'name': module.params['name']}, 'selectApplications': 'applicationid', 'selectDiscoveryRule': 'itemid', - #'selectDhosts': 'dhostid', }) + + #******# + # 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") @@ -190,26 +201,38 @@ def main(): content = zapi.get_content(zbx_class_name, 'delete', [content['result'][0][idname]]) module.exit_json(changed=True, results=content['result'], state="absent") + # Create and Update if state == 'present': - template = get_template(zapi, module.params['template_name']) - params = {'name': dname, + params = {'name': module.params['name'], 'key_': module.params['key'], 'hostid': template['templateid'], 'interfaceid': module.params['interfaceid'], - 'ruleid': get_rule_id(zapi, module.params['discoveryrule_name']), + 'ruleid': get_rule_id(zapi, module.params['discoveryrule_name'], template['templateid']), 'type': get_type(module.params['ztype']), 'value_type': get_value_type(module.params['value_type']), 'applications': get_app_ids(zapi, module.params['applications']), } + if params['type'] in [2, 5, 7, 8, 11, 15]: params.pop('interfaceid') + # Remove any None valued params + _ = [params.pop(key, None) for key in params.keys() if params[key] is None] + + #******# + # CREATE + #******# if not exists(content): - # if we didn't find it, create it 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') - # already exists, we need to update it - # let's compare properties + + #******# + # UPDATE + #******# differences = {} zab_results = content['result'][0] for key, value in params.items(): @@ -218,6 +241,11 @@ def main(): if value != zab_results['discoveryRule']['itemid']: differences[key] = value + elif key == 'applications': + app_ids = [app['applicationid'] for app in zab_results[key]] + if set(app_ids) - set(value): + differences[key] = value + elif zab_results[key] != value and zab_results[key] != str(value): differences[key] = value @@ -227,6 +255,10 @@ def main(): # We have differences and need to update differences[idname] = zab_results[idname] 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, -- cgit v1.2.3 From 176258e9c9e9254fed8ba997a80a0262b5e2ede5 Mon Sep 17 00:00:00 2001 From: Kenny Woodson Date: Tue, 22 Sep 2015 15:33:39 -0400 Subject: Fixed a bug and removed the need for template and discoveryrule --- roles/lib_zabbix/library/zbx_itemprototype.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'roles/lib_zabbix/library/zbx_itemprototype.py') diff --git a/roles/lib_zabbix/library/zbx_itemprototype.py b/roles/lib_zabbix/library/zbx_itemprototype.py index b93b7729e..75b9e25b7 100644 --- a/roles/lib_zabbix/library/zbx_itemprototype.py +++ b/roles/lib_zabbix/library/zbx_itemprototype.py @@ -157,10 +157,8 @@ def main(): value_type=dict(default='float', type='str'), delay=dict(default=60, type='int'), lifetime=dict(default=30, type='int'), - template_name=dict(default=None, required=True, type='str'), state=dict(default='present', type='str'), status=dict(default='enabled', type='str'), - discoveryrule_name=dict(default=None, required=True, type='str'), applications=dict(default=[], type='list'), ), #supports_check_mode=True @@ -175,14 +173,14 @@ def main(): zbx_class_name = 'itemprototype' idname = "itemid" state = module.params['state'] - template = get_template(zapi, module.params['template_name']) # selectInterfaces doesn't appear to be working but is needed. content = zapi.get_content(zbx_class_name, 'get', - {'search': {'name': module.params['name']}, + {'search': {'key_': module.params['key']}, 'selectApplications': 'applicationid', 'selectDiscoveryRule': 'itemid', + 'templated': True, }) #******# @@ -205,9 +203,9 @@ def main(): if state == 'present': params = {'name': module.params['name'], 'key_': module.params['key'], - 'hostid': template['templateid'], + 'hostid': content['result'][0]['hostid'], 'interfaceid': module.params['interfaceid'], - 'ruleid': get_rule_id(zapi, module.params['discoveryrule_name'], template['templateid']), + 'ruleid': content['result'][0]['discoveryRule']['itemid'], 'type': get_type(module.params['ztype']), 'value_type': get_value_type(module.params['value_type']), 'applications': get_app_ids(zapi, module.params['applications']), @@ -226,7 +224,7 @@ def main(): 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(failed=True, changed=False, results=content['error'], state="present") module.exit_json(changed=True, results=content['result'], state='present') -- cgit v1.2.3 From 984c3f7e47039be37b700536367d26ca02b61522 Mon Sep 17 00:00:00 2001 From: Kenny Woodson Date: Tue, 22 Sep 2015 15:56:46 -0400 Subject: Added descriptions and parameters required for associating prototypes to discovery rules. --- roles/lib_zabbix/library/zbx_itemprototype.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'roles/lib_zabbix/library/zbx_itemprototype.py') diff --git a/roles/lib_zabbix/library/zbx_itemprototype.py b/roles/lib_zabbix/library/zbx_itemprototype.py index 75b9e25b7..4ec1b8e02 100644 --- a/roles/lib_zabbix/library/zbx_itemprototype.py +++ b/roles/lib_zabbix/library/zbx_itemprototype.py @@ -38,12 +38,12 @@ def exists(content, key='result'): return True -def get_rule_id(zapi, discoveryrule_name, templateid): +def get_rule_id(zapi, discoveryrule_key, templateid): '''get a discoveryrule by name ''' content = zapi.get_content('discoveryrule', 'get', - {'search': {'name': discoveryrule_name}, + {'search': {'key_': discoveryrule_key}, 'output': 'extend', 'templateids': templateid, }) @@ -152,6 +152,7 @@ def main(): zbx_debug=dict(default=False, type='bool'), name=dict(default=None, type='str'), key=dict(default=None, type='str'), + description=dict(default=None, type='str'), interfaceid=dict(default=None, type='int'), ztype=dict(default='trapper', type='str'), value_type=dict(default='float', type='str'), @@ -160,6 +161,8 @@ def main(): state=dict(default='present', type='str'), status=dict(default='enabled', type='str'), applications=dict(default=[], type='list'), + template_name=dict(default=None, type='str'), + discoveryrule_key=dict(default=None, type='str'), ), #supports_check_mode=True ) @@ -173,6 +176,7 @@ def main(): zbx_class_name = 'itemprototype' idname = "itemid" state = module.params['state'] + template = get_template(zapi, module.params['template_name']) # selectInterfaces doesn't appear to be working but is needed. content = zapi.get_content(zbx_class_name, @@ -203,12 +207,13 @@ def main(): if state == 'present': params = {'name': module.params['name'], 'key_': module.params['key'], - 'hostid': content['result'][0]['hostid'], + 'hostid': template['templateid'], 'interfaceid': module.params['interfaceid'], - 'ruleid': content['result'][0]['discoveryRule']['itemid'], + 'ruleid': get_rule_id(zapi, module.params['discoveryrule_key'], template['templateid']), 'type': get_type(module.params['ztype']), 'value_type': get_value_type(module.params['value_type']), 'applications': get_app_ids(zapi, module.params['applications']), + 'description': module.params['description'], } if params['type'] in [2, 5, 7, 8, 11, 15]: -- cgit v1.2.3 From 6b3d70aec80f1cc9b4f9bd14aab062410e3d77ac Mon Sep 17 00:00:00 2001 From: Kenny Woodson Date: Wed, 7 Oct 2015 17:26:26 -0400 Subject: Fixed a bug where applicationids were not being filtered properly --- roles/lib_zabbix/library/zbx_itemprototype.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'roles/lib_zabbix/library/zbx_itemprototype.py') diff --git a/roles/lib_zabbix/library/zbx_itemprototype.py b/roles/lib_zabbix/library/zbx_itemprototype.py index 4ec1b8e02..e7fd6fa21 100644 --- a/roles/lib_zabbix/library/zbx_itemprototype.py +++ b/roles/lib_zabbix/library/zbx_itemprototype.py @@ -128,12 +128,12 @@ def get_status(status): return _status -def get_app_ids(zapi, application_names): +def get_app_ids(zapi, application_names, templateid): ''' get application ids from names ''' app_ids = [] for app_name in application_names: - content = zapi.get_content('application', 'get', {'search': {'name': app_name}}) + content = zapi.get_content('application', 'get', {'filter': {'name': app_name}, 'templateids': templateid}) if content.has_key('result'): app_ids.append(content['result'][0]['applicationid']) return app_ids @@ -212,7 +212,7 @@ def main(): 'ruleid': get_rule_id(zapi, module.params['discoveryrule_key'], template['templateid']), 'type': get_type(module.params['ztype']), 'value_type': get_value_type(module.params['value_type']), - 'applications': get_app_ids(zapi, module.params['applications']), + 'applications': get_app_ids(zapi, module.params['applications'], template['templateid']), 'description': module.params['description'], } -- cgit v1.2.3