ansible-collections / community.zabbix

Zabbix Ansible modules
http://galaxy.ansible.com/community/zabbix
Other
322 stars 284 forks source link

zabbix_host: Handling of snmp interfaces is not idempotent #656

Closed mmarkgraf-tpgroup closed 2 years ago

mmarkgraf-tpgroup commented 2 years ago
SUMMARY

community.zabbix.zabbix_host will only run successfully once when attaching snmp-interfaces. Running the module again with the exact same config will result in an error like this one:

Failed to update host somehost.nil:
('Error -32602: Invalid params., Host cannot have more than one default interface of the same type. while sending 
'{
    "jsonrpc": "2.0",
    "method": "hostinterface.create",
    "params": {
        "main": 1,
        "type": 2,
        "useip": 1,
        "ip": "10.40.3.213",
        "dns": "somehost.nil",
        "port": "3401",
        "details": {
            "version": "2",
            "bulk": "1",
            "community": "public"
        },
        "hostid": "10585"
    },
    "auth": "some-auth-token",
    "id": 22
}', -32602)

As you can see the module uses "hostinterface.create", when it should use "update".

ISSUE TYPE
COMPONENT NAME

community.zabbix.zabbix_host

ANSIBLE VERSION
ansible [core 2.11.9] 
  config file = /home/marco/temp/ansible/ansible.cfg
  configured module search path = ['/home/marco/temp/ansible/library']
  ansible python module location = /home/marco/git/ansible/.venv/lib/python3.10/site-packages/ansible
  ansible collection location = /home/marco/temp/ansible/collections
  executable location = /home/marco/git/ansible/.venv/bin/ansible
  python version = 3.10.2 (main, Jan 15 2022, 19:56:27) [GCC 11.1.0]
  jinja version = 3.0.3
  libyaml = True
CONFIGURATION
CACHE_PLUGIN(/home/marco/temp/ansible/ansible.cfg) = jsonfile
CACHE_PLUGIN_CONNECTION(/home/marco/temp/ansible/ansible.cfg) = /tmp/ansiblefactscache
CACHE_PLUGIN_TIMEOUT(/home/marco/temp/ansible/ansible.cfg) = 3600
COLLECTIONS_PATHS(/home/marco/temp/ansible/ansible.cfg) = ['/home/marco/temp/ansible/collections']
DEFAULT_GATHERING(/home/marco/temp/ansible/ansible.cfg) = smart
DEFAULT_HOST_LIST(/home/marco/temp/ansible/ansible.cfg) = ['/home/marco/temp/ansible/environments/transporeon/dv.tp.nil']
DEFAULT_LOOKUP_PLUGIN_PATH(/home/marco/temp/ansible/ansible.cfg) = ['/home/marco/temp/ansible/lookup_plugins']
DEFAULT_MODULE_PATH(/home/marco/temp/ansible/ansible.cfg) = ['/home/marco/temp/ansible/library']
DEFAULT_ROLES_PATH(/home/marco/temp/ansible/ansible.cfg) = ['/home/marco/temp/ansible/roles']
DEFAULT_STDOUT_CALLBACK(env: ANSIBLE_STDOUT_CALLBACK) = debug
DEFAULT_VAULT_PASSWORD_FILE(/home/marco/temp/ansible/ansible.cfg) = /home/marco/temp/ansible/test/fixtures/vault_password_file
INTERPRETER_PYTHON(/home/marco/temp/ansible/ansible.cfg) = python
INVENTORY_IGNORE_EXTS(/home/marco/temp/ansible/ansible.cfg) = ['~', '.orig', '.bak', '.ini', '.cfg', '.retry', '.pyc', '.pyo', '.cache']
NETWORK_GROUP_MODULES(/home/marco/temp/ansible/ansible.cfg) = ['arubaoss']
OS / ENVIRONMENT / Zabbix Version

Target OS: Debian buster

STEPS TO REPRODUCE
---
- name: try to add interface and fail
  hosts: localhost

  vars:
    tp_zabbix_host_host_name: somehost.nil
    tp_zabbix_host_state: present
    tp_zabbix_host_status: enabled
    tp_zabbix_host_interfaces:
      -
        type: snmp
        dns: "{{ ansible_fqdn }}"
        ip: "{{ ansible_default_ipv4.address }}"
        useip: 1
        # '3401' is the default for template 'Squid SNMP'
        port: 3401
        main: 1
        details:
          community: public
          version: 2
          bulk: 1
    tp_zabbix_host_server_url:  "{{ monitoring_automation_url }}"
    tp_zabbix_host_login_user: "{{ monitoring_automation_user }}"
    tp_zabbix_host_login_password: "{{ monitoring_automation_user_password }}"
    tp_zabbix_host_force: False

  tasks:

    - name: attach interface
      community.zabbix.zabbix_host:
        host_name: "{{ tp_zabbix_host_host_name }}"
        state: "{{ tp_zabbix_host_state }}"
        status: "{{ tp_zabbix_host_status }}"
        interfaces: "{{ tp_zabbix_host_interfaces }}"
        server_url: "{{ tp_zabbix_host_server_url }}"
        login_user: "{{ tp_zabbix_host_login_user }}"
        login_password: "{{ tp_zabbix_host_login_password }}"
        force: "{{ tp_zabbix_host_force }}"
      delegate_to: localhost
EXPECTED RESULTS

I expected the interface to be attached to the host.

ACTUAL RESULTS

It did on the first run, but failed on subsequent runs. See above.

D3DeFi commented 2 years ago

Hi, thank you for reporting this. Can you please also provide Zabbix server version you are running on?

mmarkgraf-tpgroup commented 2 years ago

Sure. I'm using the dockerized zabbix-server-pgsql/alpine-5.2-latest

sebneus commented 2 years ago

Maybe this is linked to a problem I found:

when you request info with zabbix_host_info the field interfaces.details returns an empty list for non-snmp interfaces - but zabbix_host expects an dictionary for this!

I have two roles adding different interfaces/templates to a host. Since we cannot add interface you always have to check the existance of the interface/host before running zabbix_host. If the second role is run for the first time we have to join the existing interface (from the first role) and the new. I get the existing agent interface with zabbix_host_info. This reply has an empty interface.details key. So, before using this with the interface in role 2 I have to delete/update that key "manually" to use it for the second run.

I am not sure if this related. I am happy to file a new bug report otherwise.

BGmot commented 2 years ago

@mmarkgraf-tpgroup can you try zabbix_host.py from https://github.com/ansible-collections/community.zabbix/pull/718 ? Zabbix 5.2 is not supported but should work. We test on 4.0, 5.0 and 6.0.

BGmot commented 2 years ago

@sebneus you can add interfaces, just specify

force: false

and the interface will be added to already existing ones (if it is not already there).

mmarkgraf-tpgroup commented 2 years ago

@BGmot zabbix_host.py from #718 is working as intended :-) And I tried both, force: True and force: False

Thanks for that!

Please note that force: True with my previously installed zabbix_host.py does the trick as well. (No idea why that was changed from the default. I'll see if it falls on my feet elsewhere...)