diff options
| author | Kenny Woodson <kwoodson@redhat.com> | 2015-08-11 17:22:40 -0400 | 
|---|---|---|
| committer | Kenny Woodson <kwoodson@redhat.com> | 2015-08-11 17:22:40 -0400 | 
| commit | 479020f56a5e593188bafcd19e7dcb56a10e3544 (patch) | |
| tree | 39a82e7eaff837506cb6232a9f943dba42738112 | |
| parent | 813bf4fb5ac36e16304ae1ee9d141e42d898c9f4 (diff) | |
| parent | a073f179b26c0d110aa6a8b7fc560ca061e4dc5c (diff) | |
| download | openshift-479020f56a5e593188bafcd19e7dcb56a10e3544.tar.gz openshift-479020f56a5e593188bafcd19e7dcb56a10e3544.tar.bz2 openshift-479020f56a5e593188bafcd19e7dcb56a10e3544.tar.xz openshift-479020f56a5e593188bafcd19e7dcb56a10e3544.zip | |
Merge pull request #446 from kwoodson/idem
Zabbix Idempotent module
| -rw-r--r-- | git/.pylintrc | 6 | ||||
| -rw-r--r-- | playbooks/adhoc/zabbix_setup/clean_zabbix.yml | 37 | ||||
| -rw-r--r-- | playbooks/adhoc/zabbix_setup/create_template.yml | 30 | ||||
| -rw-r--r-- | playbooks/adhoc/zabbix_setup/setup_zabbix.yml | 9 | ||||
| -rw-r--r-- | playbooks/adhoc/zabbix_setup/vars/template_heartbeat.yml | 28 | ||||
| -rw-r--r-- | playbooks/adhoc/zabbix_setup/vars/template_os_linux.yml | 304 | ||||
| -rw-r--r-- | roles/os_zabbix/library/__init__.py | 0 | ||||
| -rw-r--r-- | roles/os_zabbix/library/test.yml | 92 | ||||
| -rw-r--r-- | roles/os_zabbix/library/zbx_host.py | 162 | ||||
| -rw-r--r-- | roles/os_zabbix/library/zbx_hostgroup.py | 116 | ||||
| -rw-r--r-- | roles/os_zabbix/library/zbx_item.py | 160 | ||||
| -rw-r--r-- | roles/os_zabbix/library/zbx_mediatype.py | 149 | ||||
| -rw-r--r-- | roles/os_zabbix/library/zbx_template.py | 126 | ||||
| -rw-r--r-- | roles/os_zabbix/library/zbx_trigger.py | 175 | ||||
| -rw-r--r-- | roles/os_zabbix/library/zbx_user.py | 146 | ||||
| -rw-r--r-- | roles/os_zabbix/library/zbx_usergroup.py | 160 | ||||
| -rwxr-xr-x | roles/os_zabbix/library/zbxapi.py | 382 | 
17 files changed, 1406 insertions, 676 deletions
| diff --git a/git/.pylintrc b/git/.pylintrc index af8f1656f..fe6eef6de 100644 --- a/git/.pylintrc +++ b/git/.pylintrc @@ -71,7 +71,7 @@ confidence=  # no Warning level messages displayed, use"--disable=all --enable=classes  # --disable=W"  # w0511 - fixme - disabled because TODOs are acceptable -disable=E1608,W1627,E1601,E1603,E1602,E1605,E1604,E1607,E1606,W1621,W1620,W1623,W1622,W1625,W1624,W1609,W1608,W1607,W1606,W1605,W1604,W1603,W1602,W1601,W1639,W1640,I0021,W1638,I0020,W1618,W1619,W1630,W1626,W1637,W1634,W1635,W1610,W1611,W1612,W1613,W1614,W1615,W1616,W1617,W1632,W1633,W0704,W1628,W1629,W1636,W0511 +disable=E1608,W1627,E1601,E1603,E1602,E1605,E1604,E1607,E1606,W1621,W1620,W1623,W1622,W1625,W1624,W1609,W1608,W1607,W1606,W1605,W1604,W1603,W1602,W1601,W1639,W1640,I0021,W1638,I0020,W1618,W1619,W1630,W1626,W1637,W1634,W1635,W1610,W1611,W1612,W1613,W1614,W1615,W1616,W1617,W1632,W1633,W0704,W1628,W1629,W1636,W0511,R0801  [REPORTS] @@ -205,7 +205,7 @@ docstring-min-length=-1  [SIMILARITIES]  # Minimum lines number of a similarity. -min-similarity-lines=4 +min-similarity-lines=0  # Ignore comments when computing similarities.  ignore-comments=yes @@ -214,7 +214,7 @@ ignore-comments=yes  ignore-docstrings=yes  # Ignore imports when computing similarities. -ignore-imports=no +ignore-imports=yes  [VARIABLES] diff --git a/playbooks/adhoc/zabbix_setup/clean_zabbix.yml b/playbooks/adhoc/zabbix_setup/clean_zabbix.yml index 610d18b28..a31cbef65 100644 --- a/playbooks/adhoc/zabbix_setup/clean_zabbix.yml +++ b/playbooks/adhoc/zabbix_setup/clean_zabbix.yml @@ -2,67 +2,50 @@  - hosts: localhost    gather_facts: no    vars: -    # Use this for local ZAIO      g_zserver: http://localhost/zabbix/api_jsonrpc.php -      g_zuser: Admin      g_zpassword: zabbix    roles: -  - ../roles/os_zabbix +  - ../../../roles/os_zabbix    post_tasks: -  - zbxapi: +  - zbx_template:        server: "{{ g_zserver }}"        user: "{{ g_zuser }}"        password: "{{ g_zpassword }}" -      zbx_class: Template        state: list -      params: -        output: extend -        search: -          host: 'Template Heartbeat' +      name: 'Template Heartbeat'      register: templ_heartbeat -  - zbxapi: +  - zbx_template:        server: "{{ g_zserver }}"        user: "{{ g_zuser }}"        password: "{{ g_zpassword }}" -      zbx_class: Template        state: list -      params: -        output: extend -        search: -          host: 'Template App Zabbix Server' +      name: 'Template App Zabbix Server'      register: templ_zabbix_server -  - zbxapi: +  - zbx_template:        server: "{{ g_zserver }}"        user: "{{ g_zuser }}"        password: "{{ g_zpassword }}" -      zbx_class: Template        state: list -      params: -        output: extend -        search: -          host: 'Template App Zabbix Agent' +      name: 'Template App Zabbix Agent'      register: templ_zabbix_agent -  - zbxapi: +  - zbx_template:        server: "{{ g_zserver }}"        user: "{{ g_zuser }}"        password: "{{ g_zpassword }}" -      zbx_class: Template        state: list      register: templates    - debug: var=templ_heartbeat.results -  - zbxapi: +  - zbx_template:        server: "{{ g_zserver }}"        user: "{{ g_zuser }}"        password: "{{ g_zpassword }}" -      zbx_class: Template        state: absent -      params: "{{templates.results | difference(templ_zabbix_agent.results) | difference(templ_zabbix_server.results) | oo_collect('templateid') }}" -    register: template_results +    with_items: "{{ templates.results | difference(templ_zabbix_agent.results) | difference(templ_zabbix_server.results) | oo_collect('host') }}"      when:  templ_heartbeat.results | length == 0 diff --git a/playbooks/adhoc/zabbix_setup/create_template.yml b/playbooks/adhoc/zabbix_setup/create_template.yml index b055e78eb..60fb27666 100644 --- a/playbooks/adhoc/zabbix_setup/create_template.yml +++ b/playbooks/adhoc/zabbix_setup/create_template.yml @@ -2,16 +2,14 @@  - debug: var=ctp_template  - name: Create Template -  zbxapi: +  zbx_template:      server: "{{ ctp_zserver }}"      user: "{{ ctp_zuser }}"      password: "{{ ctp_zpassword }}" -    zbx_class: Template -    state: present -    params: "{{ ctp_template.params }}" -  register: ctp_created_templates +    name: "{{ ctp_template.name }}" +  register: ctp_created_template -- debug: var=ctp_created_templates +- debug: var=ctp_created_template  #- name: Create Application  #  zbxapi: @@ -22,7 +20,7 @@  #    state: present  #    params:  #      name: "{{ ctp_template.application.name}}" -#      hostid: "{{ ctp_created_templates.results[0].templateid }}" +#      hostid: "{{ ctp_created_template.results[0].templateid }}"  #      search:  #        name: "{{ ctp_template.application.name}}"  #  register: ctp_created_application @@ -30,28 +28,28 @@  #- debug: var=ctp_created_application  - name: Create Items -  zbxapi: +  zbx_item:      server: "{{ ctp_zserver }}"      user: "{{ ctp_zuser }}"      password: "{{ ctp_zpassword }}" -    zbx_class: Item -    state: present -    params: "{{ item | oo_set_zbx_item_hostid(ctp_created_templates.results) }}" +    name: "{{ item.name }}" +    key: "{{ item.key }}" +    value_type: "{{ item.value_type | default('int') }}" +    template_name: "{{ ctp_template.name }}"    with_items: ctp_template.zitems    register: ctp_created_items  #- debug: var=ctp_created_items  - name: Create Triggers -  zbxapi: +  zbx_trigger:      server: "{{ ctp_zserver }}"      user: "{{ ctp_zuser }}"      password: "{{ ctp_zpassword }}" -    zbx_class: Trigger -    state: present -    params: "{{ item }}" +    description: "{{ item.description }}" +    expression: "{{ item.expression }}" +    priority: "{{ item.priority }}"    with_items: ctp_template.ztriggers -  register: ctp_created_triggers    when: ctp_template.ztriggers is defined  #- debug: var=ctp_created_triggers diff --git a/playbooks/adhoc/zabbix_setup/setup_zabbix.yml b/playbooks/adhoc/zabbix_setup/setup_zabbix.yml index 8b44f2adf..1729194b5 100644 --- a/playbooks/adhoc/zabbix_setup/setup_zabbix.yml +++ b/playbooks/adhoc/zabbix_setup/setup_zabbix.yml @@ -5,22 +5,17 @@    - vars/template_heartbeat.yml    - vars/template_os_linux.yml    vars: -    # Use this for local ZAIO      g_zserver: http://localhost/zabbix/api_jsonrpc.php -      g_zuser: Admin      g_zpassword: zabbix    roles: -  - ../roles/os_zabbix +  - ../../../roles/os_zabbix    post_tasks: -  - zbxapi: +  - zbx_template:        server: "{{ g_zserver }}"        user: "{{ g_zuser }}"        password: "{{ g_zpassword }}" -      zbx_class: Template        state: list -      params: -        output: extend      register: templates    - debug: var=templates diff --git a/playbooks/adhoc/zabbix_setup/vars/template_heartbeat.yml b/playbooks/adhoc/zabbix_setup/vars/template_heartbeat.yml index 9d6145ec4..22cc75554 100644 --- a/playbooks/adhoc/zabbix_setup/vars/template_heartbeat.yml +++ b/playbooks/adhoc/zabbix_setup/vars/template_heartbeat.yml @@ -1,33 +1,11 @@  ---  g_template_heartbeat: -  application: -    name: Heartbeat -#output: extend -    search: -      name: Heartbeat -  params: -    name: Template Heartbeat -    host: Template Heartbeat -    groups: -    - groupid: 1 # FIXME (not real) -    output: extend -    search: -      name: Template Heartbeat +  name: Template Heartbeat    zitems:    - name: Heartbeat Ping      hostid: -    key_: heartbeat.ping -    type: 2 -    value_type: 1 -    output: extend -    search: -      key_: heartbeat.ping -    selectApplications: extend +    key: heartbeat.ping    ztriggers:    - description: 'Heartbeat.ping has failed on {HOST.NAME}'      expression: '{Template Heartbeat:heartbeat.ping.last()}<>0' -    priority: 3 -    searchWildcardsEnabled: True -    search: -      description: 'Heartbeat.ping has failed on*' -    expandExpression: True +    priority: avg diff --git a/playbooks/adhoc/zabbix_setup/vars/template_os_linux.yml b/playbooks/adhoc/zabbix_setup/vars/template_os_linux.yml index b89711632..6fab08879 100644 --- a/playbooks/adhoc/zabbix_setup/vars/template_os_linux.yml +++ b/playbooks/adhoc/zabbix_setup/vars/template_os_linux.yml @@ -1,248 +1,120 @@  ---  g_template_os_linux: -  application: -    name: OS Linux -    output: extend -    search: -      name: OS Linux -  params: -    name: Template OS Linux -    host: Template OS Linux -    groups: -    - groupid: 1 # FIXME (not real) -    output: extend -    search: -      name: Template OS Linux +  name: Template OS Linux    zitems: -  - hostid: null -    key_: kernel.uname.sysname +  - key: kernel.uname.sysname      name: kernel.uname.sysname -    search: -      key_: kernel.uname.sysname -    type: 2 -    value_type: 4 -    selectApplications: extend -  - hostid: null -    key_: kernel.all.cpu.wait.total +    value_type: string + +  - key: kernel.all.cpu.wait.total      name: kernel.all.cpu.wait.total -    search: -      key_: kernel.all.cpu.wait.total -    type: 2 -    value_type: 3 -    selectApplications: extend -  - hostid: null -    key_: kernel.all.cpu.irq.hard +    value_type: int + +  - key: kernel.all.cpu.irq.hard      name: kernel.all.cpu.irq.hard -    search: -      key_: kernel.all.cpu.irq.hard -    type: 2 -    value_type: 3 -    selectApplications: extend -  - hostid: null -    key_: kernel.all.cpu.idle +    value_type: int + +  - key: kernel.all.cpu.idle      name: kernel.all.cpu.idle -    search: -      key_: kernel.all.cpu.idle -    type: 2 -    value_type: 3 -    selectApplications: extend -  - hostid: null -    key_: kernel.uname.distro +    value_type: int + +  - key: kernel.uname.distro      name: kernel.uname.distro -    search: -      key_: kernel.uname.distro -    type: 2 -    value_type: 4 -    selectApplications: extend -  - hostid: null -    key_: kernel.uname.nodename +    value_type: string + +  - key: kernel.uname.nodename      name: kernel.uname.nodename -    search: -      key_: kernel.uname.nodename -    type: 2 -    value_type: 4 -    selectApplications: extend -  - hostid: null -    key_: kernel.all.cpu.irq.soft +    value_type: string + +  - key: kernel.all.cpu.irq.soft      name: kernel.all.cpu.irq.soft -    search: -      key_: kernel.all.cpu.irq.soft -    type: 2 -    value_type: 3 -    selectApplications: extend -  - hostid: null -    key_: kernel.all.load.15_minute +    value_type: int + +  - key: kernel.all.load.15_minute      name: kernel.all.load.15_minute -    search: -      key_: kernel.all.load.15_minute -    type: 2 -    value_type: 0 -    selectApplications: extend -  - hostid: null -    key_: kernel.all.cpu.sys +    value_type: float + +  - key: kernel.all.cpu.sys      name: kernel.all.cpu.sys -    search: -      key_: kernel.all.cpu.sys -    type: 2 -    value_type: 3 -    selectApplications: extend -  - hostid: null -    key_: kernel.all.load.5_minute +    value_type: int + +  - key: kernel.all.load.5_minute      name: kernel.all.load.5_minute -    search: -      key_: kernel.all.load.5_minute -    type: 2 -    value_type: 0 -    selectApplications: extend -  - hostid: null -    key_: mem.freemem +    value_type: float + +  - key: mem.freemem      name: mem.freemem -    search: -      key_: mem.freemem -    type: 2 -    value_type: 3 -    selectApplications: extend -  - hostid: null -    key_: kernel.all.cpu.nice +    value_type: int + +  - key: kernel.all.cpu.nice      name: kernel.all.cpu.nice -    search: -      key_: kernel.all.cpu.nice -    type: 2 -    value_type: 3 -    selectApplications: extend -  - hostid: null -    key_: mem.util.bufmem +    value_type: int + +  - key: mem.util.bufmem      name: mem.util.bufmem -    search: -      key_: mem.util.bufmem -    type: 2 -    value_type: 3 -    selectApplications: extend -  - hostid: null -    key_: swap.used +    value_type: int + +  - key: swap.used      name: swap.used -    search: -      key_: swap.used -    type: 2 -    value_type: 3 -    selectApplications: extend -  - hostid: null -    key_: kernel.all.load.1_minute +    value_type: int + +  - key: kernel.all.load.1_minute      name: kernel.all.load.1_minute -    search: -      key_: kernel.all.load.1_minute -    type: 2 -    value_type: 0 -    selectApplications: extend -  - hostid: null -    key_: kernel.uname.version +    value_type: float + +  - key: kernel.uname.version      name: kernel.uname.version -    search: -      key_: kernel.uname.version -    type: 2 -    value_type: 4 -    selectApplications: extend -  - hostid: null -    key_: swap.length +    value_type: string + +  - key: swap.length      name: swap.length -    search: -      key_: swap.length -    type: 2 -    value_type: 3 -    selectApplications: extend -  - hostid: null -    key_: mem.physmem +    value_type: int + +  - key: mem.physmem      name: mem.physmem -    search: -      key_: mem.physmem -    type: 2 -    value_type: 3 -    selectApplications: extend -  - hostid: null -    key_: kernel.all.uptime +    value_type: int + +  - key: kernel.all.uptime      name: kernel.all.uptime -    search: -      key_: kernel.all.uptime -    type: 2 -    value_type: 3 -    selectApplications: extend -  - hostid: null -    key_: swap.free +    value_type: int + +  - key: swap.free      name: swap.free -    search: -      key_: swap.free -    type: 2 -    value_type: 3 -    selectApplications: extend -  - hostid: null -    key_: mem.util.used +    value_type: int + +  - key: mem.util.used      name: mem.util.used -    search: -      key_: mem.util.used -    type: 2 -    value_type: 3 -    selectApplications: extend -  - hostid: null -    key_: kernel.all.cpu.user +    value_type: int + +  - key: kernel.all.cpu.user      name: kernel.all.cpu.user -    search: -      key_: kernel.all.cpu.user -    type: 2 -    value_type: 3 -    selectApplications: extend -  - hostid: null -    key_: kernel.uname.machine +    value_type: int + +  - key: kernel.uname.machine      name: kernel.uname.machine -    search: -      key_: kernel.uname.machine -    type: 2 -    value_type: 4 -    selectApplications: extend -  - hostid: null -    key_: hinv.ncpu +    value_type: string + +  - key: hinv.ncpu      name: hinv.ncpu -    search: -      key_: hinv.ncpu -    type: 2 -    value_type: 3 -    selectApplications: extend -  - hostid: null -    key_: mem.util.cached +    value_type: int + +  - key: mem.util.cached      name: mem.util.cached -    search: -      key_: mem.util.cached -    type: 2 -    value_type: 3 -    selectApplications: extend -  - hostid: null -    key_: kernel.all.cpu.steal +    value_type: int + +  - key: kernel.all.cpu.steal      name: kernel.all.cpu.steal -    search: -      key_: kernel.all.cpu.steal -    type: 2 -    value_type: 3 -    selectApplications: extend -  - hostid: null -    key_: kernel.all.pswitch +    value_type: int + + +  - key: kernel.all.pswitch      name: kernel.all.pswitch -    search: -      key_: kernel.all.pswitch -    type: 2 -    value_type: 3 -    selectApplications: extend -  - hostid: null -    key_: kernel.uname.release +    value_type: int + +  - key: kernel.uname.release      name: kernel.uname.release -    search: -      key_: kernel.uname.release -    type: 2 -    value_type: 4 -    selectApplications: extend -  - hostid: null -    key_: proc.nprocs +    value_type: string + +  - key: proc.nprocs      name: proc.nprocs -    search: -      key_: proc.nprocs -    type: 2 -    value_type: 3 -    selectApplications: extend +    value_type: int diff --git a/roles/os_zabbix/library/__init__.py b/roles/os_zabbix/library/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/roles/os_zabbix/library/__init__.py diff --git a/roles/os_zabbix/library/test.yml b/roles/os_zabbix/library/test.yml new file mode 100644 index 000000000..f585bcbb2 --- /dev/null +++ b/roles/os_zabbix/library/test.yml @@ -0,0 +1,92 @@ +--- +# This is a test playbook to create one of each of the zabbix ansible modules. +# ensure that the zbxapi module is installed +# ansible-playbook test.yml +- name: Test zabbix ansible module +  hosts: localhost +  gather_facts: no +  vars: +    zbx_server: http://localhost/zabbix/api_jsonrpc.php +    zbx_user: Admin +    zbx_password: zabbix + +  pre_tasks: +  - name: Create a template +    zbx_template: +      server: "{{ zbx_server }}" +      user: "{{ zbx_user }}" +      password: "{{ zbx_password }}" +      name: 'test template' +    register: template_output + +  - debug: var=template_output + +  - name: Create an item +    zbx_item: +      server: "{{ zbx_server }}" +      user: "{{ zbx_user }}" +      password: "{{ zbx_password }}" +      name: 'test item' +      key: 'kenny.item.1' +      template_name: "{{ template_output.results[0].host }}" +    register: item_output + +  - debug: var=item_output + +  - name: Create an trigger +    zbx_trigger: +      server: "{{ zbx_server }}" +      user: "{{ zbx_user }}" +      password: "{{ zbx_password }}" +      expression: '{test template:kenny.item.1.last()}>2' +      desc: 'Kenny desc' +    register: trigger_output + +  - debug: var=trigger_output + +  - name: Create a hostgroup +    zbx_hostgroup: +      server: "{{ zbx_server }}" +      user: "{{ zbx_user }}" +      password: "{{ zbx_password }}" +      name: 'kenny hostgroup' +    register: hostgroup_output + +  - debug: var=hostgroup_output + +  - name: Create a host +    zbx_host: +      server: "{{ zbx_server }}" +      user: "{{ zbx_user }}" +      password: "{{ zbx_password }}" +      name: 'kenny host' +      hostgroups: +      -  'kenny hostgroup' +    register: host_output + +  - debug: var=host_output + +  - name: Create a usergroup +    zbx_usergroup: +      server: "{{ zbx_server }}" +      user: "{{ zbx_user }}" +      password: "{{ zbx_password }}" +      name: kenny usergroup +      rights: +      - 'kenny hostgroup': rw +    register: usergroup_output + +  - debug: var=usergroup_output + +  - name: Create a user +    zbx_user: +      server: "{{ zbx_server }}" +      user: "{{ zbx_user }}" +      password: "{{ zbx_password }}" +      alias: kenny user +      passwd: zabbix +      usergroups: +      - kenny usergroup +    register: user_output + +  - debug: var=user_output diff --git a/roles/os_zabbix/library/zbx_host.py b/roles/os_zabbix/library/zbx_host.py new file mode 100644 index 000000000..d75dfdea1 --- /dev/null +++ b/roles/os_zabbix/library/zbx_host.py @@ -0,0 +1,162 @@ +#!/usr/bin/env python +''' +Zabbix host 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_group_ids(zapi, hostgroup_names): +    ''' +    get hostgroups +    ''' +    # Fetch groups by name +    group_ids = [] +    for hgr in hostgroup_names: +        content = zapi.get_content('hostgroup', 'get', {'search': {'name': hgr}}) +        if content.has_key('result'): +            group_ids.append({'groupid': content['result'][0]['groupid']}) + +    return group_ids + +def get_template_ids(zapi, template_names): +    ''' +    get related templates +    ''' +    template_ids = [] +    # Fetch templates by name +    for template_name in template_names: +        content = zapi.get_content('template', 'get', {'search': {'host': template_name}}) +        if content.has_key('result'): +            template_ids.append({'templateid': content['results'][0]['templateid']}) +    return template_ids + +def main(): +    ''' +    Ansible module for zabbix host +    ''' + +    module = AnsibleModule( +        argument_spec=dict( +            server=dict(default='https://localhost/zabbix/api_jsonrpc.php', type='str'), +            user=dict(default=None, type='str'), +            password=dict(default=None, type='str'), +            name=dict(default=None, type='str'), +            hostgroup_names=dict(default=[], type='list'), +            template_names=dict(default=[], type='list'), +            debug=dict(default=False, type='bool'), +            state=dict(default='present', type='str'), +            interfaces=dict(default=[], type='list'), +        ), +        #supports_check_mode=True +    ) + +    user = module.params.get('user', os.environ['ZABBIX_USER']) +    passwd = module.params.get('password', os.environ['ZABBIX_PASSWORD']) + +    zapi = ZabbixAPI(ZabbixConnection(module.params['server'], user, passwd, module.params['debug'])) + +    #Set the instance and the template for the rest of the calls +    zbx_class_name = 'host' +    idname = "hostid" +    hname = 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': {'host': hname}, +                                'selectGroups': 'groupid', +                                'selectParentTemplates': 'templateid', +                                'selectInterfaces': 'interfaceid', +                               }) +    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': +        params = {'host': hname, +                  'groups':  get_group_ids(zapi, module.params('hostgroup_names')), +                  'templates':  get_template_ids(zapi, module.params('template_names')), +                  'interfaces': module.params.get('interfaces', [{'type':  1,         # interface type, 1 = agent +                                                                  'main':  1,         # default interface? 1 = true +                                                                  'useip':  1,        # default interface? 1 = true +                                                                  'ip':  '127.0.0.1', # default interface? 1 = true +                                                                  'dns':  '',         # dns for host +                                                                  'port':  '10050',   # port for interface? 10050 +                                                                 }]) +                 } + +        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 == 'templates' and zab_results.has_key('parentTemplates'): +                if zab_results['parentTemplates'] != value: +                    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() diff --git a/roles/os_zabbix/library/zbx_hostgroup.py b/roles/os_zabbix/library/zbx_hostgroup.py new file mode 100644 index 000000000..a1eb875d4 --- /dev/null +++ b/roles/os_zabbix/library/zbx_hostgroup.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python +''' Ansible module for hostgroup +''' +# vim: expandtab:tabstop=4:shiftwidth=4 +# +#   Zabbix hostgroup 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.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 main(): +    ''' ansible module for hostgroup +    ''' + +    module = AnsibleModule( +        argument_spec=dict( +            server=dict(default='https://localhost/zabbix/api_jsonrpc.php', type='str'), +            user=dict(default=None, type='str'), +            password=dict(default=None, type='str'), +            name=dict(default=None, type='str'), +            debug=dict(default=False, type='bool'), +            state=dict(default='present', type='str'), +        ), +        #supports_check_mode=True +    ) + +    user = module.params.get('user', os.environ['ZABBIX_USER']) +    passwd = module.params.get('password', os.environ['ZABBIX_PASSWORD']) + +    zapi = ZabbixAPI(ZabbixConnection(module.params['server'], user, passwd, module.params['debug'])) + +    #Set the instance and the template for the rest of the calls +    zbx_class_name = 'hostgroup' +    idname = "groupid" +    hname = module.params['name'] +    state = module.params['state'] + +    content = zapi.get_content(zbx_class_name, +                               'get', +                               {'search': {'name': hname}, +                               }) +    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': +        params = {'name': hname} + +        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 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() diff --git a/roles/os_zabbix/library/zbx_item.py b/roles/os_zabbix/library/zbx_item.py new file mode 100644 index 000000000..6cfb16d48 --- /dev/null +++ b/roles/os_zabbix/library/zbx_item.py @@ -0,0 +1,160 @@ +#!/usr/bin/env python +''' + Ansible module for zabbix items +''' +# vim: expandtab:tabstop=4:shiftwidth=4 +# +#   Zabbix item 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.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_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 main(): +    ''' +    ansible zabbix module for zbx_item +    ''' + +    module = AnsibleModule( +        argument_spec=dict( +            server=dict(default='https://localhost/zabbix/api_jsonrpc.php', type='str'), +            user=dict(default=None, type='str'), +            password=dict(default=None, type='str'), +            name=dict(default=None, type='str'), +            key=dict(default=None, type='str'), +            template_name=dict(default=None, type='str'), +            zabbix_type=dict(default=2, type='int'), +            value_type=dict(default='int', type='str'), +            applications=dict(default=[], type='list'), +            debug=dict(default=False, type='bool'), +            state=dict(default='present', type='str'), +        ), +        #supports_check_mode=True +    ) + +    user = module.params.get('user', os.environ['ZABBIX_USER']) +    passwd = module.params.get('password', os.environ['ZABBIX_PASSWORD']) + +    zapi = ZabbixAPI(ZabbixConnection(module.params['server'], user, passwd, module.params['debug'])) + +    #Set the instance and the template for the rest of the calls +    zbx_class_name = 'item' +    idname = "itemid" +    state = module.params['state'] +    key = module.params['key'] +    template_name = module.params['template_name'] + +    content = zapi.get_content('template', 'get', {'search': {'host': template_name}}) +    templateid = None +    if content['result']: +        templateid = content['result'][0]['templateid'] +    else: +        module.exit_json(changed=False, +                         results='Error: Could find template with name %s for item.' % template_name, +                         state="Unkown") + +    content = zapi.get_content(zbx_class_name, +                               'get', +                               {'search': {'key_': key}, +                                'selectApplications': 'applicationid', +                               }) +    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': +        params = {'name': module.params['name'], +                  'key_': key, +                  'hostid': templateid, +                  'type': module.params['zabbix_type'], +                  'value_type': get_value_type(module.params['value_type']), +                  'applications': module.params['applications'], +                 } + +        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 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() diff --git a/roles/os_zabbix/library/zbx_mediatype.py b/roles/os_zabbix/library/zbx_mediatype.py new file mode 100644 index 000000000..a49aecd0f --- /dev/null +++ b/roles/os_zabbix/library/zbx_mediatype.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python +''' + Ansible module for mediatype +''' +# vim: expandtab:tabstop=4:shiftwidth=4 +# +#   Zabbix mediatype 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.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_mtype(mtype): +    ''' +    Transport used by the media type. +    Possible values: +    0 - email; +    1 - script; +    2 - SMS; +    3 - Jabber; +    100 - Ez Texting. +    ''' +    mtype = mtype.lower() +    media_type = None +    if mtype == 'script': +        media_type = 1 +    elif mtype == 'sms': +        media_type = 2 +    elif mtype == 'jabber': +        media_type = 3 +    elif mtype == 'script': +        media_type = 100 +    else: +        media_type = 0 + +    return media_type + +def main(): +    ''' +    Ansible zabbix module for mediatype +    ''' + +    module = AnsibleModule( +        argument_spec=dict( +            server=dict(default='https://localhost/zabbix/api_jsonrpc.php', type='str'), +            user=dict(default=None, type='str'), +            password=dict(default=None, type='str'), +            description=dict(default=None, type='str'), +            mtype=dict(default=None, type='str'), +            smtp_server=dict(default=None, type='str'), +            smtp_helo=dict(default=None, type='str'), +            smtp_email=dict(default=None, type='str'), +            debug=dict(default=False, type='bool'), +            state=dict(default='present', type='str'), +        ), +        #supports_check_mode=True +    ) + +    user = module.params.get('user', os.environ['ZABBIX_USER']) +    passwd = module.params.get('password', os.environ['ZABBIX_PASSWORD']) + +    zapi = ZabbixAPI(ZabbixConnection(module.params['server'], user, passwd, module.params['debug'])) + +    #Set the instance and the template for the rest of the calls +    zbx_class_name = 'mediatype' +    idname = "mediatypeid" +    description = module.params['description'] +    state = module.params['state'] + +    content = zapi.get_content(zbx_class_name, 'get', {'search': {'description': description}}) +    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': +        params = {'description': description, +                  'type': get_mtype(module.params['media_type']), +                  'smtp_server': module.params['smtp_server'], +                  'smtp_helo': module.params['smtp_helo'], +                  'smtp_email': module.params['smtp_email'], +                 } + +        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 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() diff --git a/roles/os_zabbix/library/zbx_template.py b/roles/os_zabbix/library/zbx_template.py new file mode 100644 index 000000000..676fa7e49 --- /dev/null +++ b/roles/os_zabbix/library/zbx_template.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python +''' +Ansible module for template +''' +# vim: expandtab:tabstop=4:shiftwidth=4 +# +#   Zabbix template 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.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 main(): +    ''' Ansible module for template +    ''' + +    module = AnsibleModule( +        argument_spec=dict( +            server=dict(default='https://localhost/zabbix/api_jsonrpc.php', type='str'), +            user=dict(default=None, type='str'), +            password=dict(default=None, type='str'), +            name=dict(default=None, type='str'), +            debug=dict(default=False, type='bool'), +            state=dict(default='present', type='str'), +        ), +        #supports_check_mode=True +    ) + +    user = module.params.get('user', os.environ['ZABBIX_USER']) +    passwd = module.params.get('password', os.environ['ZABBIX_PASSWORD']) + +    zbc = ZabbixConnection(module.params['server'], user, passwd, module.params['debug']) +    zapi = ZabbixAPI(zbc) + +    #Set the instance and the template for the rest of the calls +    zbx_class_name = 'template' +    idname = 'templateid' +    tname = module.params['name'] +    state = module.params['state'] +    # get a template, see if it exists +    content = zapi.get_content(zbx_class_name, +                               'get', +                               {'search': {'host': tname}, +                                'selectParentTemplates': 'templateid', +                                'selectGroups': 'groupid', +                                #'selectApplications': extend, +                               }) +    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': +        params = {'groups': module.params.get('groups', [{'groupid': '1'}]), +                  'host': tname, +                 } + +        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 == 'templates' and zab_results.has_key('parentTemplates'): +                if zab_results['parentTemplates'] != value: +                    differences[key] = value +            elif zab_results[key] != str(value) and zab_results[key] != value: +                differences[key] = value + +        if not differences: +            module.exit_json(changed=False, results=content['result'], 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() diff --git a/roles/os_zabbix/library/zbx_trigger.py b/roles/os_zabbix/library/zbx_trigger.py new file mode 100644 index 000000000..7cc9356c8 --- /dev/null +++ b/roles/os_zabbix/library/zbx_trigger.py @@ -0,0 +1,175 @@ +#!/usr/bin/env python +''' +ansible module for zabbix triggers +''' +# vim: expandtab:tabstop=4:shiftwidth=4 +# +#   Zabbix trigger 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.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_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_deps(zapi, deps): +    ''' get trigger dependencies +    ''' +    results = [] +    for desc in deps: +        content = zapi.get_content('trigger', +                                   'get', +                                   {'search': {'description': desc}, +                                    'expandExpression': True, +                                    'selectDependencies': 'triggerid', +                                   }) +        if content.has_key('result'): +            results.append({'triggerid': content['result'][0]['triggerid']}) + +    return results + +def main(): +    ''' +    Create a trigger in zabbix + +    Example: +    "params": { +        "description": "Processor load is too high on {HOST.NAME}", +        "expression": "{Linux server:system.cpu.load[percpu,avg1].last()}>5", +        "dependencies": [ +            { +                "triggerid": "14062" +            } +        ] +    }, + +    ''' + +    module = AnsibleModule( +        argument_spec=dict( +            server=dict(default='https://localhost/zabbix/api_jsonrpc.php', type='str'), +            user=dict(default=None, type='str'), +            password=dict(default=None, type='str'), +            expression=dict(default=None, type='str'), +            description=dict(default=None, type='str'), +            dependencies=dict(default=[], type='list'), +            priority=dict(default='avg', type='str'), +            debug=dict(default=False, type='bool'), +            state=dict(default='present', type='str'), +        ), +        #supports_check_mode=True +    ) + +    user = module.params.get('user', os.environ['ZABBIX_USER']) +    passwd = module.params.get('password', os.environ['ZABBIX_PASSWORD']) + + +    zapi = ZabbixAPI(ZabbixConnection(module.params['server'], user, passwd, module.params['debug'])) + +    #Set the instance and the template for the rest of the calls +    zbx_class_name = 'trigger' +    idname = "triggerid" +    state = module.params['state'] +    description = module.params['description'] + +    content = zapi.get_content(zbx_class_name, +                               'get', +                               {'search': {'description': description}, +                                'expandExpression': True, +                                'selectDependencies': 'triggerid', +                               }) +    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': +        params = {'description': description, +                  'expression':  module.params['expression'], +                  'dependencies': get_deps(zapi, module.params['dependencies']), +                  'priority': get_priority(module.params['priority']), +                 } + +        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 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() diff --git a/roles/os_zabbix/library/zbx_user.py b/roles/os_zabbix/library/zbx_user.py new file mode 100644 index 000000000..489023407 --- /dev/null +++ b/roles/os_zabbix/library/zbx_user.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python +''' +ansible module for zabbix users +''' +# vim: expandtab:tabstop=4:shiftwidth=4 +# +#   Zabbix user 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.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_usergroups(zapi, usergroups): +    ''' Get usergroups +    ''' +    ugroups = [] +    for ugr in usergroups: +        content = zapi.get_content('usergroup', +                                   'get', +                                   {'search': {'name': ugr}, +                                    #'selectUsers': 'userid', +                                    #'getRights': 'extend' +                                   }) +        if content['result']: +            ugroups.append({'usrgrpid': content['result'][0]['usrgrpid']}) + +    return ugroups + +def main(): +    ''' +    ansible zabbix module for users +    ''' + +    ##def user(self, name, state='present', params=None): + +    module = AnsibleModule( +        argument_spec=dict( +            server=dict(default='https://localhost/zabbix/api_jsonrpc.php', type='str'), +            user=dict(default=None, type='str'), +            password=dict(default=None, type='str'), +            alias=dict(default=None, type='str'), +            passwd=dict(default=None, type='str'), +            usergroups=dict(default=None, type='list'), +            debug=dict(default=False, type='bool'), +            state=dict(default='present', type='str'), +        ), +        #supports_check_mode=True +    ) + +    user = module.params.get('user', os.environ['ZABBIX_USER']) +    password = module.params.get('password', os.environ['ZABBIX_PASSWORD']) + +    zbc = ZabbixConnection(module.params['server'], user, password, module.params['debug']) +    zapi = ZabbixAPI(zbc) + +    ## before we can create a user media and users with media types we need media +    zbx_class_name = 'user' +    idname = "userid" +    alias = module.params['alias'] +    state = module.params['state'] + +    content = zapi.get_content(zbx_class_name, +                               'get', +                               {'output': 'extend', +                                'search': {'alias': alias}, +                                "selectUsrgrps": 'usergrpid', +                               }) +    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': +        params = {'alias': alias, +                  'passwd': module.params['passwd'], +                  'usrgrps': get_usergroups(zapi, module.params['usergroups']), +                 } + +        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 == 'passwd': +                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() diff --git a/roles/os_zabbix/library/zbx_usergroup.py b/roles/os_zabbix/library/zbx_usergroup.py new file mode 100644 index 000000000..ede4c9df1 --- /dev/null +++ b/roles/os_zabbix/library/zbx_usergroup.py @@ -0,0 +1,160 @@ +#!/usr/bin/env python +''' +zabbix ansible module for usergroups +''' +# vim: expandtab:tabstop=4:shiftwidth=4 +# +#   Zabbix usergroup 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.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_rights(zapi, rights): +    '''Get rights +    ''' +    perms = [] +    for right in rights: +        hstgrp = right.keys()[0] +        perm = right.values()[0] +        content = zapi.get_content('hostgroup', 'get', {'search': {'name': hstgrp}}) +        if content['result']: +            permission = 0 +            if perm == 'ro': +                permission = 2 +            elif perm == 'rw': +                permission = 3 +            perms.append({'id': content['result'][0]['groupid'], +                          'permission': permission}) +    return perms + +def get_userids(zapi, users): +    ''' Get userids from user aliases +    ''' +    userids = [] +    for alias in users: +        content = zapi.get_content('user', 'get', {'search': {'alias': alias}}) +        if content['result']: +            userids.append(content['result'][0]['userid']) + +    return userids + +def main(): +    ''' Ansible module for usergroup +    ''' + +    ##def usergroup(self, name, rights=None, users=None, state='present', params=None): + +    module = AnsibleModule( +        argument_spec=dict( +            server=dict(default='https://localhost/zabbix/api_jsonrpc.php', type='str'), +            user=dict(default=None, type='str'), +            password=dict(default=None, type='str'), +            name=dict(default=None, type='str'), +            rights=dict(default=[], type='list'), +            users=dict(default=[], type='list'), +            debug=dict(default=False, type='bool'), +            state=dict(default='present', type='str'), +        ), +        #supports_check_mode=True +    ) + +    user = module.params.get('user', os.environ['ZABBIX_USER']) +    passwd = module.params.get('password', os.environ['ZABBIX_PASSWORD']) + +    zapi = ZabbixAPI(ZabbixConnection(module.params['server'], user, passwd, module.params['debug'])) + +    zbx_class_name = 'usergroup' +    idname = "usrgrpid" +    uname = module.params['name'] +    state = module.params['state'] + +    content = zapi.get_content(zbx_class_name, +                               'get', +                               {'search': {'name': uname}, +                                'selectUsers': 'userid', +                               }) +    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': +        params = {'name': uname, +                  'rights': get_rights(zapi, module.params['rights']), +                  'userids': get_userids(zapi, module.params['users']), +                 } + +        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 == 'rights': +                differences['rights'] = value + +            elif key == 'userids' and zab_results.has_key('users'): +                if zab_results['users'] != value: +                    differences['userids'] = 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() diff --git a/roles/os_zabbix/library/zbxapi.py b/roles/os_zabbix/library/zbxapi.py deleted file mode 100755 index 48f294938..000000000 --- a/roles/os_zabbix/library/zbxapi.py +++ /dev/null @@ -1,382 +0,0 @@ -#!/usr/bin/env python -# vim: expandtab:tabstop=4:shiftwidth=4 -''' -   ZabbixAPI 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. -# -#  Purpose: An ansible module to communicate with zabbix. -# - -# pylint: disable=line-too-long -# Disabling line length for readability - -import json -import httplib2 -import sys -import os -import re -import copy - -class ZabbixAPIError(Exception): -    ''' -        ZabbixAPIError -        Exists to propagate errors up from the api -    ''' -    pass - -class ZabbixAPI(object): -    ''' -        ZabbixAPI class -    ''' -    classes = { -        'Action': ['create', 'delete', 'get', 'update'], -        'Alert': ['get'], -        'Application': ['create', 'delete', 'get', 'massadd', 'update'], -        'Configuration': ['export', 'import'], -        'Dcheck': ['get'], -        'Dhost': ['get'], -        'Drule': ['copy', 'create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], -        'Dservice': ['get'], -        'Event': ['acknowledge', 'get'], -        'Graph': ['create', 'delete', 'get', 'update'], -        'Graphitem': ['get'], -        'Graphprototype': ['create', 'delete', 'get', 'update'], -        'History': ['get'], -        'Hostgroup': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'massadd', 'massremove', 'massupdate', 'update'], -        'Hostinterface': ['create', 'delete', 'get', 'massadd', 'massremove', 'replacehostinterfaces', 'update'], -        'Host': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'massadd', 'massremove', 'massupdate', 'update'], -        'Hostprototype': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], -        'Httptest': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], -        'Iconmap': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], -        'Image': ['create', 'delete', 'get', 'update'], -        'Item': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], -        'Itemprototype': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], -        'Maintenance': ['create', 'delete', 'get', 'update'], -        'Map': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], -        'Mediatype': ['create', 'delete', 'get', 'update'], -        'Proxy': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], -        'Screen': ['create', 'delete', 'get', 'update'], -        'Screenitem': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update', 'updatebyposition'], -        'Script': ['create', 'delete', 'execute', 'get', 'getscriptsbyhosts', 'update'], -        'Service': ['adddependencies', 'addtimes', 'create', 'delete', 'deletedependencies', 'deletetimes', 'get', 'getsla', 'isreadable', 'iswritable', 'update'], -        'Template': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'massadd', 'massremove', 'massupdate', 'update'], -        'Templatescreen': ['copy', 'create', 'delete', 'get', 'isreadable', 'iswritable', 'update'], -        'Templatescreenitem': ['get'], -        'Trigger': ['adddependencies', 'create', 'delete', 'deletedependencies', 'get', 'isreadable', 'iswritable', 'update'], -        'Triggerprototype': ['create', 'delete', 'get', 'update'], -        'User': ['addmedia', 'create', 'delete', 'deletemedia', 'get', 'isreadable', 'iswritable', 'login', 'logout', 'update', 'updatemedia', 'updateprofile'], -        'Usergroup': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'massadd', 'massupdate', 'update'], -        'Usermacro': ['create', 'createglobal', 'delete', 'deleteglobal', 'get', 'update', 'updateglobal'], -        'Usermedia': ['get'], -    } - -    def __init__(self, data=None): -        if not data: -            data = {} -        self.server = data.get('server', None) -        self.username = data.get('user', None) -        self.password = data.get('password', None) -        if any([value == None for value in [self.server, self.username, self.password]]): -            print 'Please specify zabbix server url, username, and password.' -            sys.exit(1) - -        self.verbose = data.get('verbose', False) -        self.use_ssl = data.has_key('use_ssl') -        self.auth = None - -        for cname, _ in self.classes.items(): -            setattr(self, cname.lower(), getattr(self, cname)(self)) - -        # pylint: disable=no-member -        # This method does not exist until the metaprogramming executed -        results = self.user.login(user=self.username, password=self.password) - -        if results[0]['status'] == '200': -            if results[1].has_key('result'): -                self.auth = results[1]['result'] -            elif results[1].has_key('error'): -                print "Unable to authenticate with zabbix server. {0} ".format(results[1]['error']) -                sys.exit(1) -        else: -            print "Error in call to zabbix. Http status: {0}.".format(results[0]['status']) -            sys.exit(1) - -    def perform(self, method, rpc_params): -        ''' -        This method calls your zabbix server. - -        It requires the following parameters in order for a proper request to be processed: -            jsonrpc - the version of the JSON-RPC protocol used by the API; -                      the Zabbix API implements JSON-RPC version 2.0; -            method - the API method being called; -            rpc_params - parameters that will be passed to the API method; -            id - an arbitrary identifier of the request; -            auth - a user authentication token; since we don't have one yet, it's set to null. -        ''' -        http_method = "POST" -        jsonrpc = "2.0" -        rid = 1 - -        http = None -        if self.use_ssl: -            http = httplib2.Http() -        else: -            http = httplib2.Http(disable_ssl_certificate_validation=True,) - -        headers = {} -        headers["Content-type"] = "application/json" - -        body = { -            "jsonrpc": jsonrpc, -            "method":  method, -            "params":  rpc_params.get('params', {}), -            "id":      rid, -            'auth':    self.auth, -        } - -        if method in ['user.login', 'api.version']: -            del body['auth'] - -        body = json.dumps(body) - -        if self.verbose: -            print body -            print method -            print headers -            httplib2.debuglevel = 1 - -        response, content = http.request(self.server, http_method, body, headers) - -        if response['status'] not in ['200', '201']: -            raise ZabbixAPIError('Error calling zabbix.  Zabbix returned %s' % response['status']) - -        if self.verbose: -            print response -            print content - -        try: -            content = json.loads(content) -        except ValueError as err: -            content = {"error": err.message} - -        return response, content - -    @staticmethod -    def meta(cname, method_names): -        ''' -        This bit of metaprogramming is where the ZabbixAPI subclasses are created. -        For each of ZabbixAPI.classes we create a class from the key and methods -        from the ZabbixAPI.classes values.  We pass a reference to ZabbixAPI class -        to each subclass in order for each to be able to call the perform method. -        ''' -        def meta_method(_class, method_name): -            ''' -            This meta method allows a class to add methods to it. -            ''' -            # This template method is a stub method for each of the subclass -            # methods. -            def template_method(self, params=None, **rpc_params): -                ''' -                This template method is a stub method for each of the subclass methods. -                ''' -                if params: -                    rpc_params['params'] = params -                else: -                    rpc_params['params'] = copy.deepcopy(rpc_params) - -                return self.parent.perform(cname.lower()+"."+method_name, rpc_params) - -            template_method.__doc__ = \ -              "https://www.zabbix.com/documentation/2.4/manual/api/reference/%s/%s" % \ -              (cname.lower(), method_name) -            template_method.__name__ = method_name -            # this is where the template method is placed inside of the subclass -            # e.g. setattr(User, "create", stub_method) -            setattr(_class, template_method.__name__, template_method) - -        # This class call instantiates a subclass. e.g. User -        _class = type(cname, -                      (object,), -                      {'__doc__': \ -                      "https://www.zabbix.com/documentation/2.4/manual/api/reference/%s" % cname.lower()}) -        def __init__(self, parent): -            ''' -            This init method gets placed inside of the _class -            to allow it to be instantiated.  A reference to the parent class(ZabbixAPI) -            is passed in to allow each class access to the perform method. -            ''' -            self.parent = parent - -        # This attaches the init to the subclass. e.g. Create -        setattr(_class, __init__.__name__, __init__) -        # For each of our ZabbixAPI.classes dict values -        # Create a method and attach it to our subclass. -        # e.g.  'User': ['delete', 'get', 'updatemedia', 'updateprofile', -        #                'update', 'iswritable', 'logout', 'addmedia', 'create', -        #                'login', 'deletemedia', 'isreadable'], -        # User.delete -        # User.get -        for method_name in method_names: -            meta_method(_class, method_name) -        # Return our subclass with all methods attached -        return _class - -# Attach all ZabbixAPI.classes to ZabbixAPI class through metaprogramming -for _class_name, _method_names in ZabbixAPI.classes.items(): -    setattr(ZabbixAPI, _class_name, ZabbixAPI.meta(_class_name, _method_names)) - -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 diff_content(from_zabbix, from_user, ignore=None): -    ''' Compare passed in object to results returned from zabbix -    ''' -    terms = ['search', 'output', 'groups', 'select', 'expand', 'filter'] -    if ignore: -        terms.extend(ignore) -    regex = '(' + '|'.join(terms) + ')' -    retval = {} -    for key, value in from_user.items(): -        if re.findall(regex, key): -            continue - -        # special case here for templates.  You query templates and -        # the zabbix api returns parentTemplates.  These will obviously fail. -        # So when its templates compare against parentTemplates. -        if key == 'templates' and from_zabbix.has_key('parentTemplates'): -            if from_zabbix['parentTemplates'] != value: -                retval[key] = value - -        elif from_zabbix[key] != str(value): -            retval[key] = str(value) - -    return retval - -def main(): -    ''' -    This main method runs the ZabbixAPI Ansible Module -    ''' - -    module = AnsibleModule( -        argument_spec=dict( -            server=dict(default='https://localhost/zabbix/api_jsonrpc.php', type='str'), -            user=dict(default=None, type='str'), -            password=dict(default=None, type='str'), -            zbx_class=dict(choices=ZabbixAPI.classes.keys()), -            params=dict(), -            debug=dict(default=False, type='bool'), -            state=dict(default='present', type='str'), -            ignore=dict(default=None, type='list'), -        ), -        #supports_check_mode=True -    ) - -    user = module.params.get('user', None) -    if not user: -        user = os.environ['ZABBIX_USER'] - -    passwd = module.params.get('password', None) -    if not passwd: -        passwd = os.environ['ZABBIX_PASSWORD'] - - - -    api_data = { -        'user': user, -        'password': passwd, -        'server': module.params['server'], -        'verbose': module.params['debug'] -    } - -    if not user or not passwd or not module.params['server']: -        module.fail_json(msg='Please specify the user, password, and the zabbix server.') - -    zapi = ZabbixAPI(api_data) - -    ignore = module.params['ignore'] -    zbx_class = module.params.get('zbx_class') -    rpc_params = module.params.get('params', {}) -    state = module.params.get('state') - - -    # Get the instance we are trying to call -    zbx_class_inst = zapi.__getattribute__(zbx_class.lower()) - -    # perform get -    # Get the instance's method we are trying to call - -    zbx_action_method = zapi.__getattribute__(zbx_class.capitalize()).__dict__['get'] -    _, content = zbx_action_method(zbx_class_inst, rpc_params) - -    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") -        # If we are coming from a query, we need to pass in the correct rpc_params for delete. -        # specifically the zabbix class name + 'id' -        # if rpc_params is a list then we need to pass it. (list of ids to delete) -        idname = zbx_class.lower() + "id" -        if not isinstance(rpc_params, list) and content['result'][0].has_key(idname): -            rpc_params = [content['result'][0][idname]] - -        zbx_action_method = zapi.__getattribute__(zbx_class.capitalize()).__dict__['delete'] -        _, content = zbx_action_method(zbx_class_inst, rpc_params) -        module.exit_json(changed=True, results=content['result'], state="absent") - -    if state == 'present': -    # It's not there, create it! -        if not exists(content): -            zbx_action_method = zapi.__getattribute__(zbx_class.capitalize()).__dict__['create'] -            _, content = zbx_action_method(zbx_class_inst, rpc_params) -            module.exit_json(changed=True, results=content['result'], state='present') - -    # It's there and the same, do nothing! -        diff_params = diff_content(content['result'][0], rpc_params, ignore) -        if not diff_params: -            module.exit_json(changed=False, results=content['result'], state="present") - -        # Add the id to update with -        idname = zbx_class.lower() + "id" -        diff_params[idname] = content['result'][0][idname] - - -        ## It's there and not the same, update it! -        zbx_action_method = zapi.__getattribute__(zbx_class.capitalize()).__dict__['update'] -        _, content = zbx_action_method(zbx_class_inst, diff_params) -        module.exit_json(changed=True, results=content, 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() - | 
