mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
removing zabbix modules and their references due to migration to a dedicated collection (#11)
This commit is contained in:
parent
2728cfe59d
commit
24405289fe
51 changed files with 2 additions and 12729 deletions
66
.github/BOTMETA.yml
vendored
66
.github/BOTMETA.yml
vendored
|
@ -160,7 +160,6 @@ files:
|
|||
$doc_fragments/xenserver.py:
|
||||
maintainers: bvitnik
|
||||
labels: xenserver
|
||||
$doc_fragments/zabbix.py:
|
||||
$filters/gcp_kms_filters.py:
|
||||
$filters/json_query.py:
|
||||
$filters/random_mac.py:
|
||||
|
@ -1181,70 +1180,6 @@ files:
|
|||
authors: bhcopeland
|
||||
$modules/monitoring/uptimerobot.py:
|
||||
authors: nate-kingsley
|
||||
$modules/monitoring/zabbix/:
|
||||
authors: sky-joker
|
||||
maintainers: D3DeFi rubentsirunyan
|
||||
ignore: ryansb
|
||||
$modules/monitoring/zabbix/zabbix_action.py:
|
||||
authors: K-DOT rubentsirunyan
|
||||
maintainers: D3DeFi sky-joker
|
||||
ignore: ryansb
|
||||
$modules/monitoring/zabbix/zabbix_group.py:
|
||||
authors: cove harrisongu
|
||||
maintainers: $team_zabbix
|
||||
ignore: cove
|
||||
$modules/monitoring/zabbix/zabbix_group_info.py:
|
||||
authors: RedWhiteMiko
|
||||
maintainers: $team_zabbix
|
||||
ignore: ryansb
|
||||
$modules/monitoring/zabbix/zabbix_host.py:
|
||||
authors: cove dj-wasabi eikef harrisongu
|
||||
maintainers: $team_zabbix
|
||||
ignore: cove
|
||||
$modules/monitoring/zabbix/zabbix_host_events_info.py:
|
||||
authors: stravassac
|
||||
maintainers: $team_zabbix
|
||||
ignore: ryansb
|
||||
$modules/monitoring/zabbix/zabbix_host_info.py:
|
||||
authors: RedWhiteMiko
|
||||
maintainers: $team_zabbix
|
||||
ignore: ryansb
|
||||
$modules/monitoring/zabbix/zabbix_hostmacro.py:
|
||||
authors: cove
|
||||
maintainers: $team_zabbix
|
||||
ignore: cove
|
||||
$modules/monitoring/zabbix/zabbix_maintenance.py:
|
||||
authors: abulimov
|
||||
maintainers: $team_zabbix
|
||||
ignore: ryansb
|
||||
$modules/monitoring/zabbix/zabbix_map.py:
|
||||
authors: Akint
|
||||
maintainers: $team_zabbix
|
||||
ignore: ryansb
|
||||
$modules/monitoring/zabbix/zabbix_mediatype.py:
|
||||
authors: rubentsirunyan
|
||||
maintainers: D3DeFi sky-joker
|
||||
ignore: ryansb
|
||||
$modules/monitoring/zabbix/zabbix_proxy.py:
|
||||
authors: akomic
|
||||
maintainers: $team_zabbix
|
||||
ignore: ryansb
|
||||
$modules/monitoring/zabbix/zabbix_screen.py:
|
||||
authors: cove harrisongu
|
||||
maintainers: $team_zabbix
|
||||
ignore: cove
|
||||
$modules/monitoring/zabbix/zabbix_service.py:
|
||||
authors: emriver
|
||||
maintainers: $team_zabbix
|
||||
ignore: ryansb
|
||||
$modules/monitoring/zabbix/zabbix_template.py:
|
||||
authors: D3DeFi logan2211 sookido
|
||||
maintainers: rubentsirunyan sky-joker
|
||||
ignore: ryansb
|
||||
$modules/monitoring/zabbix/zabbix_valuemap.py:
|
||||
authors: rubentsirunyan
|
||||
maintainers: D3DeFi sky-joker
|
||||
ignore: ryansb
|
||||
$modules/net_tools/cloudflare_dns.py:
|
||||
authors: mgruener
|
||||
maintainers: andreaso
|
||||
|
@ -2302,4 +2237,3 @@ macros:
|
|||
team_suse: commel dcermak evrardjp lrupp toabctl
|
||||
team_virt: joshainglis karmab
|
||||
team_vultr: Spredzy resmo
|
||||
team_zabbix: D3DeFi rubentsirunyan sky-joker
|
||||
|
|
|
@ -608,14 +608,6 @@ plugin_routing:
|
|||
deprecation:
|
||||
removal_date: TBD
|
||||
warning_text: see plugin documentation for details
|
||||
zabbix_group_facts:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
warning_text: see plugin documentation for details
|
||||
zabbix_host_facts:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
warning_text: see plugin documentation for details
|
||||
ldap_attr:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright: (c) 2017, Ansible, Inc
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
|
||||
class ModuleDocFragment(object):
|
||||
|
||||
# Standard documentation fragment
|
||||
DOCUMENTATION = r'''
|
||||
options:
|
||||
server_url:
|
||||
description:
|
||||
- URL of Zabbix server, with protocol (http or https).
|
||||
C(url) is an alias for C(server_url).
|
||||
required: true
|
||||
type: str
|
||||
aliases: [ url ]
|
||||
login_user:
|
||||
description:
|
||||
- Zabbix user name.
|
||||
type: str
|
||||
required: true
|
||||
login_password:
|
||||
description:
|
||||
- Zabbix user password.
|
||||
type: str
|
||||
required: true
|
||||
http_login_user:
|
||||
description:
|
||||
- Basic Auth login
|
||||
type: str
|
||||
http_login_password:
|
||||
description:
|
||||
- Basic Auth password
|
||||
type: str
|
||||
timeout:
|
||||
description:
|
||||
- The timeout of API request (seconds).
|
||||
type: int
|
||||
default: 10
|
||||
validate_certs:
|
||||
description:
|
||||
- If set to False, SSL certificates will not be validated. This should only be used on personally controlled sites using self-signed certificates.
|
||||
type: bool
|
||||
default: yes
|
||||
notes:
|
||||
- If you use I(login_password=zabbix), the word "zabbix" is replaced by "********" in all module output, because I(login_password) uses C(no_log).
|
||||
See L(this FAQ,https://docs.ansible.com/ansible/latest/network/user_guide/faq.html#why-is-my-output-sometimes-replaced-with) for more information.
|
||||
'''
|
File diff suppressed because it is too large
Load diff
|
@ -1,208 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# (c) 2013-2014, Epic Games, Inc.
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: zabbix_group
|
||||
short_description: Create/delete Zabbix host groups
|
||||
description:
|
||||
- Create host groups if they do not exist.
|
||||
- Delete existing host groups if they exist.
|
||||
author:
|
||||
- "Cove (@cove)"
|
||||
- "Tony Minfei Ding (!UNKNOWN)"
|
||||
- "Harrison Gu (@harrisongu)"
|
||||
requirements:
|
||||
- "python >= 2.6"
|
||||
- "zabbix-api >= 0.5.4"
|
||||
options:
|
||||
state:
|
||||
description:
|
||||
- Create or delete host group.
|
||||
required: false
|
||||
type: str
|
||||
default: "present"
|
||||
choices: [ "present", "absent" ]
|
||||
host_groups:
|
||||
description:
|
||||
- List of host groups to create or delete.
|
||||
required: true
|
||||
type: list
|
||||
elements: str
|
||||
aliases: [ "host_group" ]
|
||||
|
||||
extends_documentation_fragment:
|
||||
- community.general.zabbix
|
||||
|
||||
|
||||
notes:
|
||||
- Too many concurrent updates to the same group may cause Zabbix to return errors, see examples for a workaround if needed.
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
# Base create host groups example
|
||||
- name: Create host groups
|
||||
local_action:
|
||||
module: zabbix_group
|
||||
server_url: http://monitor.example.com
|
||||
login_user: username
|
||||
login_password: password
|
||||
state: present
|
||||
host_groups:
|
||||
- Example group1
|
||||
- Example group2
|
||||
|
||||
# Limit the Zabbix group creations to one host since Zabbix can return an error when doing concurrent updates
|
||||
- name: Create host groups
|
||||
local_action:
|
||||
module: zabbix_group
|
||||
server_url: http://monitor.example.com
|
||||
login_user: username
|
||||
login_password: password
|
||||
state: present
|
||||
host_groups:
|
||||
- Example group1
|
||||
- Example group2
|
||||
when: inventory_hostname==groups['group_name'][0]
|
||||
'''
|
||||
|
||||
|
||||
import atexit
|
||||
import traceback
|
||||
|
||||
try:
|
||||
from zabbix_api import ZabbixAPI
|
||||
from zabbix_api import Already_Exists
|
||||
|
||||
HAS_ZABBIX_API = True
|
||||
except ImportError:
|
||||
ZBX_IMP_ERR = traceback.format_exc()
|
||||
HAS_ZABBIX_API = False
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
|
||||
|
||||
class HostGroup(object):
|
||||
def __init__(self, module, zbx):
|
||||
self._module = module
|
||||
self._zapi = zbx
|
||||
|
||||
# create host group(s) if not exists
|
||||
def create_host_group(self, group_names):
|
||||
try:
|
||||
group_add_list = []
|
||||
for group_name in group_names:
|
||||
result = self._zapi.hostgroup.get({'filter': {'name': group_name}})
|
||||
if not result:
|
||||
try:
|
||||
if self._module.check_mode:
|
||||
self._module.exit_json(changed=True)
|
||||
self._zapi.hostgroup.create({'name': group_name})
|
||||
group_add_list.append(group_name)
|
||||
except Already_Exists:
|
||||
return group_add_list
|
||||
return group_add_list
|
||||
except Exception as e:
|
||||
self._module.fail_json(msg="Failed to create host group(s): %s" % e)
|
||||
|
||||
# delete host group(s)
|
||||
def delete_host_group(self, group_ids):
|
||||
try:
|
||||
if self._module.check_mode:
|
||||
self._module.exit_json(changed=True)
|
||||
self._zapi.hostgroup.delete(group_ids)
|
||||
except Exception as e:
|
||||
self._module.fail_json(msg="Failed to delete host group(s), Exception: %s" % e)
|
||||
|
||||
# get group ids by name
|
||||
def get_group_ids(self, host_groups):
|
||||
group_ids = []
|
||||
|
||||
group_list = self._zapi.hostgroup.get({'output': 'extend', 'filter': {'name': host_groups}})
|
||||
for group in group_list:
|
||||
group_id = group['groupid']
|
||||
group_ids.append(group_id)
|
||||
return group_ids, group_list
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
server_url=dict(type='str', required=True, aliases=['url']),
|
||||
login_user=dict(type='str', required=True),
|
||||
login_password=dict(type='str', required=True, no_log=True),
|
||||
http_login_user=dict(type='str', required=False, default=None),
|
||||
http_login_password=dict(type='str', required=False, default=None, no_log=True),
|
||||
validate_certs=dict(type='bool', required=False, default=True),
|
||||
host_groups=dict(type='list', required=True, aliases=['host_group']),
|
||||
state=dict(type='str', default="present", choices=['present', 'absent']),
|
||||
timeout=dict(type='int', default=10)
|
||||
),
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
if not HAS_ZABBIX_API:
|
||||
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'), exception=ZBX_IMP_ERR)
|
||||
|
||||
server_url = module.params['server_url']
|
||||
login_user = module.params['login_user']
|
||||
login_password = module.params['login_password']
|
||||
http_login_user = module.params['http_login_user']
|
||||
http_login_password = module.params['http_login_password']
|
||||
validate_certs = module.params['validate_certs']
|
||||
host_groups = module.params['host_groups']
|
||||
state = module.params['state']
|
||||
timeout = module.params['timeout']
|
||||
|
||||
zbx = None
|
||||
|
||||
# login to zabbix
|
||||
try:
|
||||
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
|
||||
validate_certs=validate_certs)
|
||||
zbx.login(login_user, login_password)
|
||||
atexit.register(zbx.logout)
|
||||
except Exception as e:
|
||||
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
|
||||
|
||||
hostGroup = HostGroup(module, zbx)
|
||||
|
||||
group_ids = []
|
||||
group_list = []
|
||||
if host_groups:
|
||||
group_ids, group_list = hostGroup.get_group_ids(host_groups)
|
||||
|
||||
if state == "absent":
|
||||
# delete host groups
|
||||
if group_ids:
|
||||
delete_group_names = []
|
||||
hostGroup.delete_host_group(group_ids)
|
||||
for group in group_list:
|
||||
delete_group_names.append(group['name'])
|
||||
module.exit_json(changed=True,
|
||||
result="Successfully deleted host group(s): %s." % ",".join(delete_group_names))
|
||||
else:
|
||||
module.exit_json(changed=False, result="No host group(s) to delete.")
|
||||
else:
|
||||
# create host groups
|
||||
group_add_list = hostGroup.create_host_group(host_groups)
|
||||
if len(group_add_list) > 0:
|
||||
module.exit_json(changed=True, result="Successfully created host group(s): %s" % group_add_list)
|
||||
else:
|
||||
module.exit_json(changed=False)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1 +0,0 @@
|
|||
zabbix_group_info.py
|
|
@ -1,132 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# (c) me@mimiko.me
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
RETURN = r'''
|
||||
---
|
||||
host_groups:
|
||||
description: List of Zabbix groups.
|
||||
returned: success
|
||||
type: dict
|
||||
sample: [ { "flags": "0", "groupid": "33", "internal": "0", "name": "Hostgruup A" } ]
|
||||
'''
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: zabbix_group_info
|
||||
short_description: Gather information about Zabbix hostgroup
|
||||
description:
|
||||
- This module allows you to search for Zabbix hostgroup entries.
|
||||
- This module was called C(zabbix_group_facts) before Ansible 2.9. The usage did not change.
|
||||
author:
|
||||
- "Michael Miko (@RedWhiteMiko)"
|
||||
requirements:
|
||||
- "python >= 2.6"
|
||||
- "zabbix-api >= 0.5.4"
|
||||
options:
|
||||
hostgroup_name:
|
||||
description:
|
||||
- Name of the hostgroup in Zabbix.
|
||||
- hostgroup is the unique identifier used and cannot be updated using this module.
|
||||
required: true
|
||||
type: list
|
||||
elements: str
|
||||
extends_documentation_fragment:
|
||||
- community.general.zabbix
|
||||
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
- name: Get hostgroup info
|
||||
local_action:
|
||||
module: zabbix_group_info
|
||||
server_url: http://monitor.example.com
|
||||
login_user: username
|
||||
login_password: password
|
||||
hostgroup_name:
|
||||
- ExampleHostgroup
|
||||
timeout: 10
|
||||
'''
|
||||
|
||||
|
||||
import atexit
|
||||
import traceback
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
|
||||
try:
|
||||
from zabbix_api import ZabbixAPI
|
||||
HAS_ZABBIX_API = True
|
||||
except ImportError:
|
||||
ZBX_IMP_ERR = traceback.format_exc()
|
||||
HAS_ZABBIX_API = False
|
||||
|
||||
|
||||
class Host(object):
|
||||
def __init__(self, module, zbx):
|
||||
self._module = module
|
||||
self._zapi = zbx
|
||||
|
||||
def get_group_ids_by_group_names(self, group_names):
|
||||
group_list = self._zapi.hostgroup.get({'output': 'extend', 'filter': {'name': group_names}})
|
||||
if len(group_list) < 1:
|
||||
self._module.fail_json(msg="Hostgroup not found: %s" % group_names)
|
||||
return group_list
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
server_url=dict(type='str', required=True, aliases=['url']),
|
||||
login_user=dict(type='str', required=True),
|
||||
login_password=dict(type='str', required=True, no_log=True),
|
||||
hostgroup_name=dict(type='list', required=True),
|
||||
http_login_user=dict(type='str', required=False, default=None),
|
||||
http_login_password=dict(type='str', required=False, default=None, no_log=True),
|
||||
validate_certs=dict(type='bool', required=False, default=True),
|
||||
timeout=dict(type='int', default=10)
|
||||
),
|
||||
supports_check_mode=True
|
||||
)
|
||||
if module._name == 'zabbix_group_facts':
|
||||
module.deprecate("The 'zabbix_group_facts' module has been renamed to 'zabbix_group_info'", version='2.13')
|
||||
|
||||
if not HAS_ZABBIX_API:
|
||||
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'), exception=ZBX_IMP_ERR)
|
||||
|
||||
server_url = module.params['server_url']
|
||||
login_user = module.params['login_user']
|
||||
login_password = module.params['login_password']
|
||||
http_login_user = module.params['http_login_user']
|
||||
http_login_password = module.params['http_login_password']
|
||||
validate_certs = module.params['validate_certs']
|
||||
hostgroup_name = module.params['hostgroup_name']
|
||||
timeout = module.params['timeout']
|
||||
|
||||
zbx = None
|
||||
# login to zabbix
|
||||
try:
|
||||
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
|
||||
validate_certs=validate_certs)
|
||||
zbx.login(login_user, login_password)
|
||||
atexit.register(zbx.logout)
|
||||
except Exception as e:
|
||||
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
|
||||
|
||||
host = Host(module, zbx)
|
||||
host_groups = host.get_group_ids_by_group_names(hostgroup_name)
|
||||
module.exit_json(host_groups=host_groups)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
File diff suppressed because it is too large
Load diff
|
@ -1,336 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# (c) stephane.travassac@fr.clara.net
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
RETURN = '''
|
||||
---
|
||||
triggers_ok:
|
||||
description: Host Zabbix Triggers in OK state
|
||||
returned: On success
|
||||
type: complex
|
||||
contains:
|
||||
comments:
|
||||
description: Additional description of the trigger
|
||||
type: str
|
||||
description:
|
||||
description: Name of the trigger
|
||||
type: str
|
||||
error:
|
||||
description: Error text if there have been any problems when updating the state of the trigger
|
||||
type: str
|
||||
expression:
|
||||
description: Reduced trigger expression
|
||||
type: str
|
||||
flags:
|
||||
description: Origin of the trigger
|
||||
type: int
|
||||
lastchange:
|
||||
description: Time when the trigger last changed its state (timestamp)
|
||||
type: int
|
||||
priority:
|
||||
description: Severity of the trigger
|
||||
type: int
|
||||
state:
|
||||
description: State of the trigger
|
||||
type: int
|
||||
status:
|
||||
description: Whether the trigger is enabled or disabled
|
||||
type: int
|
||||
templateid:
|
||||
description: ID of the parent template trigger
|
||||
type: int
|
||||
triggerid:
|
||||
description: ID of the trigger
|
||||
type: int
|
||||
type:
|
||||
description: Whether the trigger can generate multiple problem events
|
||||
type: int
|
||||
url:
|
||||
description: URL associated with the trigger
|
||||
type: str
|
||||
value:
|
||||
description: Whether the trigger is in OK or problem state
|
||||
type: int
|
||||
triggers_problem:
|
||||
description: Host Zabbix Triggers in problem state. See trigger and event objects in API documentation of your zabbix version for more
|
||||
returned: On success
|
||||
type: complex
|
||||
contains:
|
||||
comments:
|
||||
description: Additional description of the trigger
|
||||
type: str
|
||||
description:
|
||||
description: Name of the trigger
|
||||
type: str
|
||||
error:
|
||||
description: Error text if there have been any problems when updating the state of the trigger
|
||||
type: str
|
||||
expression:
|
||||
description: Reduced trigger expression
|
||||
type: str
|
||||
flags:
|
||||
description: Origin of the trigger
|
||||
type: int
|
||||
last_event:
|
||||
description: last event informations
|
||||
type: complex
|
||||
contains:
|
||||
acknowledged:
|
||||
description: If set to true return only acknowledged events
|
||||
type: int
|
||||
acknowledges:
|
||||
description: acknowledges informations
|
||||
type: complex
|
||||
contains:
|
||||
alias:
|
||||
description: Account who acknowledge
|
||||
type: str
|
||||
clock:
|
||||
description: Time when the event was created (timestamp)
|
||||
type: int
|
||||
message:
|
||||
description: Text of the acknowledgement message
|
||||
type: str
|
||||
clock:
|
||||
description: Time when the event was created (timestamp)
|
||||
type: int
|
||||
eventid:
|
||||
description: ID of the event
|
||||
type: int
|
||||
value:
|
||||
description: State of the related object
|
||||
type: int
|
||||
lastchange:
|
||||
description: Time when the trigger last changed its state (timestamp)
|
||||
type: int
|
||||
priority:
|
||||
description: Severity of the trigger
|
||||
type: int
|
||||
state:
|
||||
description: State of the trigger
|
||||
type: int
|
||||
status:
|
||||
description: Whether the trigger is enabled or disabled
|
||||
type: int
|
||||
templateid:
|
||||
description: ID of the parent template trigger
|
||||
type: int
|
||||
triggerid:
|
||||
description: ID of the trigger
|
||||
type: int
|
||||
type:
|
||||
description: Whether the trigger can generate multiple problem events
|
||||
type: int
|
||||
url:
|
||||
description: URL associated with the trigger
|
||||
type: str
|
||||
value:
|
||||
description: Whether the trigger is in OK or problem state
|
||||
type: int
|
||||
'''
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: zabbix_host_events_info
|
||||
short_description: Get all triggers about a Zabbix host
|
||||
description:
|
||||
- This module allows you to see if a Zabbix host have no active alert to make actions on it.
|
||||
For this case use module Ansible 'fail' to exclude host in trouble.
|
||||
- Length of "triggers_ok" allow if template's triggers exist for Zabbix Host
|
||||
author:
|
||||
- "Stéphane Travassac (@stravassac)"
|
||||
requirements:
|
||||
- "python >= 2.7"
|
||||
- "zabbix-api >= 0.5.3"
|
||||
options:
|
||||
host_identifier:
|
||||
description:
|
||||
- Identifier of Zabbix Host
|
||||
required: true
|
||||
type: str
|
||||
host_id_type:
|
||||
description:
|
||||
- Type of host_identifier
|
||||
choices:
|
||||
- hostname
|
||||
- visible_name
|
||||
- hostid
|
||||
required: false
|
||||
default: hostname
|
||||
type: str
|
||||
trigger_severity:
|
||||
description:
|
||||
- Zabbix severity for search filter
|
||||
default: average
|
||||
required: false
|
||||
choices:
|
||||
- not_classified
|
||||
- information
|
||||
- warning
|
||||
- average
|
||||
- high
|
||||
- disaster
|
||||
type: str
|
||||
extends_documentation_fragment:
|
||||
- community.general.zabbix
|
||||
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: exclude machine if alert active on it
|
||||
zabbix_host_events_info:
|
||||
server_url: "{{ zabbix_url }}"
|
||||
login_user: "{{ lookup('env','ZABBIX_USER') }}"
|
||||
login_password: "{{ lookup('env','ZABBIX_PASSWORD') }}"
|
||||
host_identifier: "{{inventory_hostname}}"
|
||||
host_id_type: "hostname"
|
||||
timeout: 120
|
||||
register: zbx_host
|
||||
delegate_to: localhost
|
||||
- fail:
|
||||
msg: "machine alert in zabbix"
|
||||
when: zbx_host['triggers_problem']|length > 0
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
import atexit
|
||||
import traceback
|
||||
|
||||
try:
|
||||
from zabbix_api import ZabbixAPI
|
||||
|
||||
HAS_ZABBIX_API = True
|
||||
except ImportError:
|
||||
ZBX_IMP_ERR = traceback.format_exc()
|
||||
HAS_ZABBIX_API = False
|
||||
|
||||
|
||||
class Host(object):
|
||||
def __init__(self, module, zbx):
|
||||
self._module = module
|
||||
self._zapi = zbx
|
||||
|
||||
def get_host(self, host_identifier, host_inventory, search_key):
|
||||
""" Get host by hostname|visible_name|hostid """
|
||||
host = self._zapi.host.get(
|
||||
{'output': 'extend', 'selectParentTemplates': ['name'], 'filter': {search_key: host_identifier},
|
||||
'selectInventory': host_inventory})
|
||||
if len(host) < 1:
|
||||
self._module.fail_json(msg="Host not found: %s" % host_identifier)
|
||||
else:
|
||||
return host[0]
|
||||
|
||||
def get_triggers_by_host_id_in_problem_state(self, host_id, trigger_severity):
|
||||
""" Get triggers in problem state from a hostid"""
|
||||
# https://www.zabbix.com/documentation/3.4/manual/api/reference/trigger/get
|
||||
output = 'extend'
|
||||
triggers_list = self._zapi.trigger.get({'output': output, 'hostids': host_id,
|
||||
'min_severity': trigger_severity})
|
||||
return triggers_list
|
||||
|
||||
def get_last_event_by_trigger_id(self, triggers_id):
|
||||
""" Get the last event from triggerid"""
|
||||
output = ['eventid', 'clock', 'acknowledged', 'value']
|
||||
select_acknowledges = ['clock', 'alias', 'message']
|
||||
event = self._zapi.event.get({'output': output, 'objectids': triggers_id,
|
||||
'select_acknowledges': select_acknowledges, "limit": 1, "sortfield": "clock",
|
||||
"sortorder": "DESC"})
|
||||
return event[0]
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
server_url=dict(type='str', required=True, aliases=['url']),
|
||||
login_user=dict(type='str', required=True),
|
||||
login_password=dict(type='str', required=True, no_log=True),
|
||||
http_login_user=dict(type='str', required=False, default=None),
|
||||
http_login_password=dict(type='str', required=False, default=None, no_log=True),
|
||||
host_identifier=dict(type='str', required=True),
|
||||
host_id_type=dict(
|
||||
default='hostname',
|
||||
type='str',
|
||||
choices=['hostname', 'visible_name', 'hostid']),
|
||||
trigger_severity=dict(
|
||||
type='str',
|
||||
required=False,
|
||||
default='average',
|
||||
choices=['not_classified', 'information', 'warning', 'average', 'high', 'disaster']),
|
||||
validate_certs=dict(type='bool', required=False, default=True),
|
||||
timeout=dict(type='int', default=10),
|
||||
|
||||
),
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
if not HAS_ZABBIX_API:
|
||||
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'),
|
||||
exception=ZBX_IMP_ERR)
|
||||
|
||||
trigger_severity_map = {'not_classified': 0, 'information': 1, 'warning': 2, 'average': 3, 'high': 4, 'disaster': 5}
|
||||
server_url = module.params['server_url']
|
||||
login_user = module.params['login_user']
|
||||
login_password = module.params['login_password']
|
||||
http_login_user = module.params['http_login_user']
|
||||
http_login_password = module.params['http_login_password']
|
||||
validate_certs = module.params['validate_certs']
|
||||
host_id = module.params['host_identifier']
|
||||
host_id_type = module.params['host_id_type']
|
||||
trigger_severity = trigger_severity_map[module.params['trigger_severity']]
|
||||
timeout = module.params['timeout']
|
||||
|
||||
host_inventory = 'hostid'
|
||||
zbx = None
|
||||
# login to zabbix
|
||||
try:
|
||||
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
|
||||
validate_certs=validate_certs)
|
||||
zbx.login(login_user, login_password)
|
||||
atexit.register(zbx.logout)
|
||||
except Exception as e:
|
||||
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
|
||||
|
||||
host = Host(module, zbx)
|
||||
|
||||
if host_id_type == 'hostname':
|
||||
zabbix_host = host.get_host(host_id, host_inventory, 'host')
|
||||
host_id = zabbix_host['hostid']
|
||||
|
||||
elif host_id_type == 'visible_name':
|
||||
zabbix_host = host.get_host(host_id, host_inventory, 'name')
|
||||
host_id = zabbix_host['hostid']
|
||||
|
||||
elif host_id_type == 'hostid':
|
||||
''' check hostid exist'''
|
||||
zabbix_host = host.get_host(host_id, host_inventory, 'hostid')
|
||||
|
||||
triggers = host.get_triggers_by_host_id_in_problem_state(host_id, trigger_severity)
|
||||
|
||||
triggers_ok = []
|
||||
triggers_problem = []
|
||||
for trigger in triggers:
|
||||
# tGet last event for trigger with problem value = 1
|
||||
# https://www.zabbix.com/documentation/3.4/manual/api/reference/trigger/object
|
||||
if int(trigger['value']) == 1:
|
||||
event = host.get_last_event_by_trigger_id(trigger['triggerid'])
|
||||
trigger['last_event'] = event
|
||||
triggers_problem.append(trigger)
|
||||
else:
|
||||
triggers_ok.append(trigger)
|
||||
|
||||
module.exit_json(ok=True, triggers_ok=triggers_ok, triggers_problem=triggers_problem)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1 +0,0 @@
|
|||
zabbix_host_info.py
|
|
@ -1,252 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# (c) me@mimiko.me
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
RETURN = r'''
|
||||
---
|
||||
hosts:
|
||||
description: List of Zabbix hosts. See https://www.zabbix.com/documentation/4.0/manual/api/reference/host/get for list of host values.
|
||||
returned: success
|
||||
type: dict
|
||||
sample: [ { "available": "1", "description": "", "disable_until": "0", "error": "", "flags": "0", "groups": ["1"], "host": "Host A", ... } ]
|
||||
'''
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: zabbix_host_info
|
||||
short_description: Gather information about Zabbix host
|
||||
description:
|
||||
- This module allows you to search for Zabbix host entries.
|
||||
- This module was called C(zabbix_host_facts) before Ansible 2.9. The usage did not change.
|
||||
author:
|
||||
- "Michael Miko (@RedWhiteMiko)"
|
||||
requirements:
|
||||
- "python >= 2.6"
|
||||
- "zabbix-api >= 0.5.4"
|
||||
options:
|
||||
host_name:
|
||||
description:
|
||||
- Name of the host in Zabbix.
|
||||
- host_name is the unique identifier used and cannot be updated using this module.
|
||||
- Required when I(host_ip) is not used.
|
||||
required: false
|
||||
type: str
|
||||
host_ip:
|
||||
description:
|
||||
- Host interface IP of the host in Zabbix.
|
||||
- Required when I(host_name) is not used.
|
||||
required: false
|
||||
type: list
|
||||
elements: str
|
||||
exact_match:
|
||||
description:
|
||||
- Find the exact match
|
||||
type: bool
|
||||
default: no
|
||||
remove_duplicate:
|
||||
description:
|
||||
- Remove duplicate host from host result
|
||||
type: bool
|
||||
default: yes
|
||||
host_inventory:
|
||||
description:
|
||||
- List of host inventory keys to display in result.
|
||||
- Whole host inventory is retrieved if keys are not specified.
|
||||
type: list
|
||||
elements: str
|
||||
required: false
|
||||
extends_documentation_fragment:
|
||||
- community.general.zabbix
|
||||
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
- name: Get host info
|
||||
local_action:
|
||||
module: zabbix_host_info
|
||||
server_url: http://monitor.example.com
|
||||
login_user: username
|
||||
login_password: password
|
||||
host_name: ExampleHost
|
||||
host_ip: 127.0.0.1
|
||||
timeout: 10
|
||||
exact_match: no
|
||||
remove_duplicate: yes
|
||||
|
||||
- name: Reduce host inventory information to provided keys
|
||||
local_action:
|
||||
module: zabbix_host_info
|
||||
server_url: http://monitor.example.com
|
||||
login_user: username
|
||||
login_password: password
|
||||
host_name: ExampleHost
|
||||
host_inventory:
|
||||
- os
|
||||
- tag
|
||||
host_ip: 127.0.0.1
|
||||
timeout: 10
|
||||
exact_match: no
|
||||
remove_duplicate: yes
|
||||
'''
|
||||
|
||||
|
||||
import atexit
|
||||
import traceback
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
|
||||
try:
|
||||
from zabbix_api import ZabbixAPI
|
||||
HAS_ZABBIX_API = True
|
||||
except ImportError:
|
||||
ZBX_IMP_ERR = traceback.format_exc()
|
||||
HAS_ZABBIX_API = False
|
||||
|
||||
|
||||
class Host(object):
|
||||
def __init__(self, module, zbx):
|
||||
self._module = module
|
||||
self._zapi = zbx
|
||||
|
||||
def get_hosts_by_host_name(self, host_name, exact_match, host_inventory):
|
||||
""" Get host by host name """
|
||||
search_key = 'search'
|
||||
if exact_match:
|
||||
search_key = 'filter'
|
||||
host_list = self._zapi.host.get({
|
||||
'output': 'extend',
|
||||
'selectParentTemplates': ['name'],
|
||||
search_key: {'host': [host_name]},
|
||||
'selectInventory': host_inventory,
|
||||
'selectGroups': 'extend',
|
||||
'selectTags': 'extend',
|
||||
'selectMacros': 'extend'
|
||||
})
|
||||
if len(host_list) < 1:
|
||||
self._module.fail_json(msg="Host not found: %s" % host_name)
|
||||
else:
|
||||
return host_list
|
||||
|
||||
def get_hosts_by_ip(self, host_ips, host_inventory):
|
||||
""" Get host by host ip(s) """
|
||||
hostinterfaces = self._zapi.hostinterface.get({
|
||||
'output': 'extend',
|
||||
'filter': {
|
||||
'ip': host_ips
|
||||
}
|
||||
})
|
||||
if len(hostinterfaces) < 1:
|
||||
self._module.fail_json(msg="Host not found: %s" % host_ips)
|
||||
host_list = []
|
||||
for hostinterface in hostinterfaces:
|
||||
host = self._zapi.host.get({
|
||||
'output': 'extend',
|
||||
'selectGroups': 'extend',
|
||||
'selectParentTemplates': ['name'],
|
||||
'hostids': hostinterface['hostid'],
|
||||
'selectInventory': host_inventory,
|
||||
'selectTags': 'extend',
|
||||
'selectMacros': 'extend'
|
||||
})
|
||||
host[0]['hostinterfaces'] = hostinterface
|
||||
host_list.append(host[0])
|
||||
return host_list
|
||||
|
||||
def delete_duplicate_hosts(self, hosts):
|
||||
""" Delete duplicated hosts """
|
||||
unique_hosts = []
|
||||
listed_hostnames = []
|
||||
for zabbix_host in hosts:
|
||||
if zabbix_host['name'] in listed_hostnames:
|
||||
continue
|
||||
unique_hosts.append(zabbix_host)
|
||||
listed_hostnames.append(zabbix_host['name'])
|
||||
return unique_hosts
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
server_url=dict(type='str', required=True, aliases=['url']),
|
||||
login_user=dict(type='str', required=True),
|
||||
login_password=dict(type='str', required=True, no_log=True),
|
||||
host_name=dict(type='str', default='', required=False),
|
||||
host_ip=dict(type='list', default=[], required=False),
|
||||
http_login_user=dict(type='str', required=False, default=None),
|
||||
http_login_password=dict(type='str', required=False, default=None, no_log=True),
|
||||
validate_certs=dict(type='bool', required=False, default=True),
|
||||
timeout=dict(type='int', default=10),
|
||||
exact_match=dict(type='bool', required=False, default=False),
|
||||
remove_duplicate=dict(type='bool', required=False, default=True),
|
||||
host_inventory=dict(type='list', default=[], required=False)
|
||||
),
|
||||
supports_check_mode=True
|
||||
)
|
||||
if module._name == 'zabbix_host_facts':
|
||||
module.deprecate("The 'zabbix_host_facts' module has been renamed to 'zabbix_host_info'", version='2.13')
|
||||
|
||||
if not HAS_ZABBIX_API:
|
||||
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'), exception=ZBX_IMP_ERR)
|
||||
|
||||
server_url = module.params['server_url']
|
||||
login_user = module.params['login_user']
|
||||
login_password = module.params['login_password']
|
||||
http_login_user = module.params['http_login_user']
|
||||
http_login_password = module.params['http_login_password']
|
||||
validate_certs = module.params['validate_certs']
|
||||
host_name = module.params['host_name']
|
||||
host_ips = module.params['host_ip']
|
||||
timeout = module.params['timeout']
|
||||
exact_match = module.params['exact_match']
|
||||
is_remove_duplicate = module.params['remove_duplicate']
|
||||
host_inventory = module.params['host_inventory']
|
||||
|
||||
if not host_inventory:
|
||||
host_inventory = 'extend'
|
||||
|
||||
zbx = None
|
||||
# login to zabbix
|
||||
try:
|
||||
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
|
||||
validate_certs=validate_certs)
|
||||
zbx.login(login_user, login_password)
|
||||
atexit.register(zbx.logout)
|
||||
except Exception as e:
|
||||
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
|
||||
|
||||
host = Host(module, zbx)
|
||||
|
||||
if host_name:
|
||||
hosts = host.get_hosts_by_host_name(host_name, exact_match, host_inventory)
|
||||
if is_remove_duplicate:
|
||||
hosts = host.delete_duplicate_hosts(hosts)
|
||||
extended_hosts = []
|
||||
for zabbix_host in hosts:
|
||||
zabbix_host['hostinterfaces'] = host._zapi.hostinterface.get({
|
||||
'output': 'extend', 'hostids': zabbix_host['hostid']
|
||||
})
|
||||
extended_hosts.append(zabbix_host)
|
||||
module.exit_json(ok=True, hosts=extended_hosts)
|
||||
|
||||
elif host_ips:
|
||||
extended_hosts = host.get_hosts_by_ip(host_ips, host_inventory)
|
||||
if is_remove_duplicate:
|
||||
hosts = host.delete_duplicate_hosts(extended_hosts)
|
||||
module.exit_json(ok=True, hosts=extended_hosts)
|
||||
else:
|
||||
module.exit_json(ok=False, hosts=[], result="No Host present")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1,264 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# (c) 2013-2014, Epic Games, Inc.
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: zabbix_hostmacro
|
||||
short_description: Create/update/delete Zabbix host macros
|
||||
description:
|
||||
- manages Zabbix host macros, it can create, update or delete them.
|
||||
author:
|
||||
- "Cove (@cove)"
|
||||
- Dean Hailin Song (!UNKNOWN)
|
||||
requirements:
|
||||
- "python >= 2.6"
|
||||
- "zabbix-api >= 0.5.4"
|
||||
options:
|
||||
host_name:
|
||||
description:
|
||||
- Name of the host.
|
||||
required: true
|
||||
type: str
|
||||
macro_name:
|
||||
description:
|
||||
- Name of the host macro in zabbix native format C({$MACRO}) or simple format C(MACRO).
|
||||
required: true
|
||||
type: str
|
||||
macro_value:
|
||||
description:
|
||||
- Value of the host macro.
|
||||
- Required if I(state=present).
|
||||
type: str
|
||||
state:
|
||||
description:
|
||||
- State of the macro.
|
||||
- On C(present), it will create if macro does not exist or update the macro if the associated data is different.
|
||||
- On C(absent) will remove a macro if it exists.
|
||||
required: false
|
||||
choices: ['present', 'absent']
|
||||
type: str
|
||||
default: "present"
|
||||
force:
|
||||
description:
|
||||
- Only updates an existing macro if set to C(yes).
|
||||
default: 'yes'
|
||||
type: bool
|
||||
|
||||
extends_documentation_fragment:
|
||||
- community.general.zabbix
|
||||
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
- name: Create new host macro or update an existing macro's value
|
||||
local_action:
|
||||
module: zabbix_hostmacro
|
||||
server_url: http://monitor.example.com
|
||||
login_user: username
|
||||
login_password: password
|
||||
host_name: ExampleHost
|
||||
macro_name: EXAMPLE.MACRO
|
||||
macro_value: Example value
|
||||
state: present
|
||||
|
||||
# Values with curly brackets need to be quoted otherwise they will be interpreted as a dictionary
|
||||
- name: Create new host macro in Zabbix native format
|
||||
local_action:
|
||||
module: zabbix_hostmacro
|
||||
server_url: http://monitor.example.com
|
||||
login_user: username
|
||||
login_password: password
|
||||
host_name: ExampleHost
|
||||
macro_name: "{$EXAMPLE.MACRO}"
|
||||
macro_value: Example value
|
||||
state: present
|
||||
|
||||
- name: Delete existing host macro
|
||||
local_action:
|
||||
module: zabbix_hostmacro
|
||||
server_url: http://monitor.example.com
|
||||
login_user: username
|
||||
login_password: password
|
||||
host_name: ExampleHost
|
||||
macro_name: "{$EXAMPLE.MACRO}"
|
||||
state: absent
|
||||
'''
|
||||
|
||||
|
||||
import atexit
|
||||
import traceback
|
||||
|
||||
try:
|
||||
from zabbix_api import ZabbixAPI
|
||||
HAS_ZABBIX_API = True
|
||||
except ImportError:
|
||||
ZBX_IMP_ERR = traceback.format_exc()
|
||||
HAS_ZABBIX_API = False
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
|
||||
|
||||
class HostMacro(object):
|
||||
def __init__(self, module, zbx):
|
||||
self._module = module
|
||||
self._zapi = zbx
|
||||
|
||||
# get host id by host name
|
||||
def get_host_id(self, host_name):
|
||||
try:
|
||||
host_list = self._zapi.host.get({'output': 'extend', 'filter': {'host': host_name}})
|
||||
if len(host_list) < 1:
|
||||
self._module.fail_json(msg="Host not found: %s" % host_name)
|
||||
else:
|
||||
host_id = host_list[0]['hostid']
|
||||
return host_id
|
||||
except Exception as e:
|
||||
self._module.fail_json(msg="Failed to get the host %s id: %s." % (host_name, e))
|
||||
|
||||
# get host macro
|
||||
def get_host_macro(self, macro_name, host_id):
|
||||
try:
|
||||
host_macro_list = self._zapi.usermacro.get(
|
||||
{"output": "extend", "selectSteps": "extend", 'hostids': [host_id], 'filter': {'macro': macro_name}})
|
||||
if len(host_macro_list) > 0:
|
||||
return host_macro_list[0]
|
||||
return None
|
||||
except Exception as e:
|
||||
self._module.fail_json(msg="Failed to get host macro %s: %s" % (macro_name, e))
|
||||
|
||||
# create host macro
|
||||
def create_host_macro(self, macro_name, macro_value, host_id):
|
||||
try:
|
||||
if self._module.check_mode:
|
||||
self._module.exit_json(changed=True)
|
||||
self._zapi.usermacro.create({'hostid': host_id, 'macro': macro_name, 'value': macro_value})
|
||||
self._module.exit_json(changed=True, result="Successfully added host macro %s" % macro_name)
|
||||
except Exception as e:
|
||||
self._module.fail_json(msg="Failed to create host macro %s: %s" % (macro_name, e))
|
||||
|
||||
# update host macro
|
||||
def update_host_macro(self, host_macro_obj, macro_name, macro_value):
|
||||
host_macro_id = host_macro_obj['hostmacroid']
|
||||
if host_macro_obj['macro'] == macro_name and host_macro_obj['value'] == macro_value:
|
||||
self._module.exit_json(changed=False, result="Host macro %s already up to date" % macro_name)
|
||||
try:
|
||||
if self._module.check_mode:
|
||||
self._module.exit_json(changed=True)
|
||||
self._zapi.usermacro.update({'hostmacroid': host_macro_id, 'value': macro_value})
|
||||
self._module.exit_json(changed=True, result="Successfully updated host macro %s" % macro_name)
|
||||
except Exception as e:
|
||||
self._module.fail_json(msg="Failed to update host macro %s: %s" % (macro_name, e))
|
||||
|
||||
# delete host macro
|
||||
def delete_host_macro(self, host_macro_obj, macro_name):
|
||||
host_macro_id = host_macro_obj['hostmacroid']
|
||||
try:
|
||||
if self._module.check_mode:
|
||||
self._module.exit_json(changed=True)
|
||||
self._zapi.usermacro.delete([host_macro_id])
|
||||
self._module.exit_json(changed=True, result="Successfully deleted host macro %s" % macro_name)
|
||||
except Exception as e:
|
||||
self._module.fail_json(msg="Failed to delete host macro %s: %s" % (macro_name, e))
|
||||
|
||||
|
||||
def normalize_macro_name(macro_name):
|
||||
# Zabbix handles macro names in upper case characters
|
||||
if ':' in macro_name:
|
||||
macro_name = ':'.join([macro_name.split(':')[0].upper(), ':'.join(macro_name.split(':')[1:])])
|
||||
else:
|
||||
macro_name = macro_name.upper()
|
||||
|
||||
# Valid format for macro is {$MACRO}
|
||||
if not macro_name.startswith('{$'):
|
||||
macro_name = '{$' + macro_name
|
||||
if not macro_name.endswith('}'):
|
||||
macro_name = macro_name + '}'
|
||||
|
||||
return macro_name
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
server_url=dict(type='str', required=True, aliases=['url']),
|
||||
login_user=dict(type='str', required=True),
|
||||
login_password=dict(type='str', required=True, no_log=True),
|
||||
http_login_user=dict(type='str', required=False, default=None),
|
||||
http_login_password=dict(type='str', required=False, default=None, no_log=True),
|
||||
validate_certs=dict(type='bool', required=False, default=True),
|
||||
host_name=dict(type='str', required=True),
|
||||
macro_name=dict(type='str', required=True),
|
||||
macro_value=dict(type='str', required=False),
|
||||
state=dict(type='str', default='present', choices=['present', 'absent']),
|
||||
timeout=dict(type='int', default=10),
|
||||
force=dict(type='bool', default=True)
|
||||
),
|
||||
required_if=[
|
||||
['state', 'present', ['macro_value']]
|
||||
],
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
if not HAS_ZABBIX_API:
|
||||
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'), exception=ZBX_IMP_ERR)
|
||||
|
||||
server_url = module.params['server_url']
|
||||
login_user = module.params['login_user']
|
||||
login_password = module.params['login_password']
|
||||
http_login_user = module.params['http_login_user']
|
||||
http_login_password = module.params['http_login_password']
|
||||
validate_certs = module.params['validate_certs']
|
||||
host_name = module.params['host_name']
|
||||
macro_name = normalize_macro_name(module.params['macro_name'])
|
||||
macro_value = module.params['macro_value']
|
||||
state = module.params['state']
|
||||
timeout = module.params['timeout']
|
||||
force = module.params['force']
|
||||
|
||||
zbx = None
|
||||
# login to zabbix
|
||||
try:
|
||||
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
|
||||
validate_certs=validate_certs)
|
||||
zbx.login(login_user, login_password)
|
||||
atexit.register(zbx.logout)
|
||||
except Exception as e:
|
||||
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
|
||||
|
||||
host_macro_class_obj = HostMacro(module, zbx)
|
||||
|
||||
if host_name:
|
||||
host_id = host_macro_class_obj.get_host_id(host_name)
|
||||
host_macro_obj = host_macro_class_obj.get_host_macro(macro_name, host_id)
|
||||
|
||||
if state == 'absent':
|
||||
if not host_macro_obj:
|
||||
module.exit_json(changed=False, msg="Host Macro %s does not exist" % macro_name)
|
||||
else:
|
||||
# delete a macro
|
||||
host_macro_class_obj.delete_host_macro(host_macro_obj, macro_name)
|
||||
else:
|
||||
if not host_macro_obj:
|
||||
# create host macro
|
||||
host_macro_class_obj.create_host_macro(macro_name, macro_value, host_id)
|
||||
elif force:
|
||||
# update host macro
|
||||
host_macro_class_obj.update_host_macro(host_macro_obj, macro_name, macro_value)
|
||||
else:
|
||||
module.exit_json(changed=False, result="Host macro %s already exists and force is set to no" % macro_name)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1,402 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# (c) 2013, Alexander Bulimov <lazywolf0@gmail.com>
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
|
||||
module: zabbix_maintenance
|
||||
short_description: Create Zabbix maintenance windows
|
||||
description:
|
||||
- This module will let you create Zabbix maintenance windows.
|
||||
author: "Alexander Bulimov (@abulimov)"
|
||||
requirements:
|
||||
- "python >= 2.6"
|
||||
- "zabbix-api >= 0.5.4"
|
||||
options:
|
||||
state:
|
||||
description:
|
||||
- Create or remove a maintenance window. Maintenance window to remove is identified by name.
|
||||
default: present
|
||||
choices: [ "present", "absent" ]
|
||||
type: str
|
||||
host_names:
|
||||
description:
|
||||
- Hosts to manage maintenance window for.
|
||||
- B(Required) option when I(state=present) and I(host_groups) is not used.
|
||||
aliases: [ "host_name" ]
|
||||
type: list
|
||||
elements: str
|
||||
host_groups:
|
||||
description:
|
||||
- Host groups to manage maintenance window for.
|
||||
- B(Required) option when I(state=present) and I(host_names) is not used.
|
||||
aliases: [ "host_group" ]
|
||||
type: list
|
||||
elements: str
|
||||
minutes:
|
||||
description:
|
||||
- Length of maintenance window in minutes.
|
||||
default: 10
|
||||
type: int
|
||||
name:
|
||||
description:
|
||||
- Unique name of maintenance window.
|
||||
required: true
|
||||
type: str
|
||||
desc:
|
||||
description:
|
||||
- Short description of maintenance window.
|
||||
default: Created by Ansible
|
||||
type: str
|
||||
collect_data:
|
||||
description:
|
||||
- Type of maintenance. With data collection, or without.
|
||||
type: bool
|
||||
default: 'yes'
|
||||
|
||||
extends_documentation_fragment:
|
||||
- community.general.zabbix
|
||||
|
||||
|
||||
notes:
|
||||
- Useful for setting hosts in maintenance mode before big update,
|
||||
and removing maintenance window after update.
|
||||
- Module creates maintenance window from now() to now() + minutes,
|
||||
so if Zabbix server's time and host's time are not synchronized,
|
||||
you will get strange results.
|
||||
- Install required module with 'pip install zabbix-api' command.
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
- name: Create a named maintenance window for host www1 for 90 minutes
|
||||
zabbix_maintenance:
|
||||
name: Update of www1
|
||||
host_name: www1.example.com
|
||||
state: present
|
||||
minutes: 90
|
||||
server_url: https://monitoring.example.com
|
||||
login_user: ansible
|
||||
login_password: pAsSwOrD
|
||||
|
||||
- name: Create a named maintenance window for host www1 and host groups Office and Dev
|
||||
zabbix_maintenance:
|
||||
name: Update of www1
|
||||
host_name: www1.example.com
|
||||
host_groups:
|
||||
- Office
|
||||
- Dev
|
||||
state: present
|
||||
server_url: https://monitoring.example.com
|
||||
login_user: ansible
|
||||
login_password: pAsSwOrD
|
||||
|
||||
- name: Create a named maintenance window for hosts www1 and db1, without data collection.
|
||||
zabbix_maintenance:
|
||||
name: update
|
||||
host_names:
|
||||
- www1.example.com
|
||||
- db1.example.com
|
||||
state: present
|
||||
collect_data: False
|
||||
server_url: https://monitoring.example.com
|
||||
login_user: ansible
|
||||
login_password: pAsSwOrD
|
||||
|
||||
- name: Remove maintenance window by name
|
||||
zabbix_maintenance:
|
||||
name: Test1
|
||||
state: absent
|
||||
server_url: https://monitoring.example.com
|
||||
login_user: ansible
|
||||
login_password: pAsSwOrD
|
||||
'''
|
||||
|
||||
|
||||
import atexit
|
||||
import datetime
|
||||
import time
|
||||
import traceback
|
||||
|
||||
try:
|
||||
from zabbix_api import ZabbixAPI
|
||||
HAS_ZABBIX_API = True
|
||||
except ImportError:
|
||||
ZBX_IMP_ERR = traceback.format_exc()
|
||||
HAS_ZABBIX_API = False
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
|
||||
|
||||
def create_maintenance(zbx, group_ids, host_ids, start_time, maintenance_type, period, name, desc):
|
||||
end_time = start_time + period
|
||||
try:
|
||||
zbx.maintenance.create(
|
||||
{
|
||||
"groupids": group_ids,
|
||||
"hostids": host_ids,
|
||||
"name": name,
|
||||
"maintenance_type": maintenance_type,
|
||||
"active_since": str(start_time),
|
||||
"active_till": str(end_time),
|
||||
"description": desc,
|
||||
"timeperiods": [{
|
||||
"timeperiod_type": "0",
|
||||
"start_date": str(start_time),
|
||||
"period": str(period),
|
||||
}]
|
||||
}
|
||||
)
|
||||
# zabbix_api can call sys.exit() so we need to catch SystemExit here
|
||||
except (Exception, SystemExit) as e:
|
||||
return 1, None, str(e)
|
||||
return 0, None, None
|
||||
|
||||
|
||||
def update_maintenance(zbx, maintenance_id, group_ids, host_ids, start_time, maintenance_type, period, desc):
|
||||
end_time = start_time + period
|
||||
try:
|
||||
zbx.maintenance.update(
|
||||
{
|
||||
"maintenanceid": maintenance_id,
|
||||
"groupids": group_ids,
|
||||
"hostids": host_ids,
|
||||
"maintenance_type": maintenance_type,
|
||||
"active_since": str(start_time),
|
||||
"active_till": str(end_time),
|
||||
"description": desc,
|
||||
"timeperiods": [{
|
||||
"timeperiod_type": "0",
|
||||
"start_date": str(start_time),
|
||||
"period": str(period),
|
||||
}]
|
||||
}
|
||||
)
|
||||
# zabbix_api can call sys.exit() so we need to catch SystemExit here
|
||||
except (Exception, SystemExit) as e:
|
||||
return 1, None, str(e)
|
||||
return 0, None, None
|
||||
|
||||
|
||||
def get_maintenance(zbx, name):
|
||||
try:
|
||||
maintenances = zbx.maintenance.get(
|
||||
{
|
||||
"filter":
|
||||
{
|
||||
"name": name,
|
||||
},
|
||||
"selectGroups": "extend",
|
||||
"selectHosts": "extend"
|
||||
}
|
||||
)
|
||||
# zabbix_api can call sys.exit() so we need to catch SystemExit here
|
||||
except (Exception, SystemExit) as e:
|
||||
return 1, None, str(e)
|
||||
|
||||
for maintenance in maintenances:
|
||||
maintenance["groupids"] = [group["groupid"] for group in maintenance["groups"]] if "groups" in maintenance else []
|
||||
maintenance["hostids"] = [host["hostid"] for host in maintenance["hosts"]] if "hosts" in maintenance else []
|
||||
return 0, maintenance, None
|
||||
|
||||
return 0, None, None
|
||||
|
||||
|
||||
def delete_maintenance(zbx, maintenance_id):
|
||||
try:
|
||||
zbx.maintenance.delete([maintenance_id])
|
||||
# zabbix_api can call sys.exit() so we need to catch SystemExit here
|
||||
except (Exception, SystemExit) as e:
|
||||
return 1, None, str(e)
|
||||
return 0, None, None
|
||||
|
||||
|
||||
def get_group_ids(zbx, host_groups):
|
||||
group_ids = []
|
||||
for group in host_groups:
|
||||
try:
|
||||
result = zbx.hostgroup.get(
|
||||
{
|
||||
"output": "extend",
|
||||
"filter":
|
||||
{
|
||||
"name": group
|
||||
}
|
||||
}
|
||||
)
|
||||
# zabbix_api can call sys.exit() so we need to catch SystemExit here
|
||||
except (Exception, SystemExit) as e:
|
||||
return 1, None, str(e)
|
||||
|
||||
if not result:
|
||||
return 1, None, "Group id for group %s not found" % group
|
||||
|
||||
group_ids.append(result[0]["groupid"])
|
||||
|
||||
return 0, group_ids, None
|
||||
|
||||
|
||||
def get_host_ids(zbx, host_names):
|
||||
host_ids = []
|
||||
for host in host_names:
|
||||
try:
|
||||
result = zbx.host.get(
|
||||
{
|
||||
"output": "extend",
|
||||
"filter":
|
||||
{
|
||||
"name": host
|
||||
}
|
||||
}
|
||||
)
|
||||
# zabbix_api can call sys.exit() so we need to catch SystemExit here
|
||||
except (Exception, SystemExit) as e:
|
||||
return 1, None, str(e)
|
||||
|
||||
if not result:
|
||||
return 1, None, "Host id for host %s not found" % host
|
||||
|
||||
host_ids.append(result[0]["hostid"])
|
||||
|
||||
return 0, host_ids, None
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
state=dict(type='str', required=False, default='present', choices=['present', 'absent']),
|
||||
server_url=dict(type='str', required=True, aliases=['url']),
|
||||
host_names=dict(type='list', required=False, default=None, aliases=['host_name']),
|
||||
minutes=dict(type='int', required=False, default=10),
|
||||
host_groups=dict(type='list', required=False, default=None, aliases=['host_group']),
|
||||
login_user=dict(type='str', required=True),
|
||||
login_password=dict(type='str', required=True, no_log=True),
|
||||
validate_certs=dict(type='bool', required=False, default=True),
|
||||
http_login_user=dict(type='str', required=False, default=None),
|
||||
http_login_password=dict(type='str', required=False, default=None, no_log=True),
|
||||
name=dict(type='str', required=True),
|
||||
desc=dict(type='str', required=False, default="Created by Ansible"),
|
||||
collect_data=dict(type='bool', required=False, default=True),
|
||||
timeout=dict(type='int', default=10),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
if not HAS_ZABBIX_API:
|
||||
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'), exception=ZBX_IMP_ERR)
|
||||
|
||||
host_names = module.params['host_names']
|
||||
host_groups = module.params['host_groups']
|
||||
state = module.params['state']
|
||||
login_user = module.params['login_user']
|
||||
login_password = module.params['login_password']
|
||||
http_login_user = module.params['http_login_user']
|
||||
http_login_password = module.params['http_login_password']
|
||||
validate_certs = module.params['validate_certs']
|
||||
minutes = module.params['minutes']
|
||||
name = module.params['name']
|
||||
desc = module.params['desc']
|
||||
server_url = module.params['server_url']
|
||||
collect_data = module.params['collect_data']
|
||||
timeout = module.params['timeout']
|
||||
|
||||
if collect_data:
|
||||
maintenance_type = 0
|
||||
else:
|
||||
maintenance_type = 1
|
||||
|
||||
try:
|
||||
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
|
||||
validate_certs=validate_certs)
|
||||
zbx.login(login_user, login_password)
|
||||
atexit.register(zbx.logout)
|
||||
# zabbix_api can call sys.exit() so we need to catch SystemExit here
|
||||
except (Exception, SystemExit) as e:
|
||||
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
|
||||
|
||||
changed = False
|
||||
|
||||
if state == "present":
|
||||
|
||||
if not host_names and not host_groups:
|
||||
module.fail_json(msg="At least one host_name or host_group must be defined for each created maintenance.")
|
||||
|
||||
now = datetime.datetime.now().replace(second=0)
|
||||
start_time = time.mktime(now.timetuple())
|
||||
period = 60 * int(minutes) # N * 60 seconds
|
||||
|
||||
if host_groups:
|
||||
(rc, group_ids, error) = get_group_ids(zbx, host_groups)
|
||||
if rc != 0:
|
||||
module.fail_json(msg="Failed to get group_ids: %s" % error)
|
||||
else:
|
||||
group_ids = []
|
||||
|
||||
if host_names:
|
||||
(rc, host_ids, error) = get_host_ids(zbx, host_names)
|
||||
if rc != 0:
|
||||
module.fail_json(msg="Failed to get host_ids: %s" % error)
|
||||
else:
|
||||
host_ids = []
|
||||
|
||||
(rc, maintenance, error) = get_maintenance(zbx, name)
|
||||
if rc != 0:
|
||||
module.fail_json(msg="Failed to check maintenance %s existence: %s" % (name, error))
|
||||
|
||||
if maintenance and (
|
||||
sorted(group_ids) != sorted(maintenance["groupids"]) or
|
||||
sorted(host_ids) != sorted(maintenance["hostids"]) or
|
||||
str(maintenance_type) != maintenance["maintenance_type"] or
|
||||
str(int(start_time)) != maintenance["active_since"] or
|
||||
str(int(start_time + period)) != maintenance["active_till"]
|
||||
):
|
||||
if module.check_mode:
|
||||
changed = True
|
||||
else:
|
||||
(rc, data, error) = update_maintenance(zbx, maintenance["maintenanceid"], group_ids, host_ids, start_time, maintenance_type, period, desc)
|
||||
if rc == 0:
|
||||
changed = True
|
||||
else:
|
||||
module.fail_json(msg="Failed to update maintenance: %s" % error)
|
||||
|
||||
if not maintenance:
|
||||
if module.check_mode:
|
||||
changed = True
|
||||
else:
|
||||
(rc, data, error) = create_maintenance(zbx, group_ids, host_ids, start_time, maintenance_type, period, name, desc)
|
||||
if rc == 0:
|
||||
changed = True
|
||||
else:
|
||||
module.fail_json(msg="Failed to create maintenance: %s" % error)
|
||||
|
||||
if state == "absent":
|
||||
|
||||
(rc, maintenance, error) = get_maintenance(zbx, name)
|
||||
if rc != 0:
|
||||
module.fail_json(msg="Failed to check maintenance %s existence: %s" % (name, error))
|
||||
|
||||
if maintenance:
|
||||
if module.check_mode:
|
||||
changed = True
|
||||
else:
|
||||
(rc, data, error) = delete_maintenance(zbx, maintenance["maintenanceid"])
|
||||
if rc == 0:
|
||||
changed = True
|
||||
else:
|
||||
module.fail_json(msg="Failed to remove maintenance: %s" % error)
|
||||
|
||||
module.exit_json(changed=changed)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1,829 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# (c) 2017-2018, Antony Alekseyev <antony.alekseyev@gmail.com>
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: zabbix_map
|
||||
author:
|
||||
- "Antony Alekseyev (@Akint)"
|
||||
short_description: Create/update/delete Zabbix maps
|
||||
description:
|
||||
- "This module allows you to create, modify and delete Zabbix map entries,
|
||||
using Graphviz binaries and text description written in DOT language.
|
||||
Nodes of the graph will become map elements and edges will become links between map elements.
|
||||
See U(https://en.wikipedia.org/wiki/DOT_(graph_description_language)) and U(https://www.graphviz.org/) for details.
|
||||
Inspired by U(http://blog.zabbix.com/maps-for-the-lazy/)."
|
||||
- "The following extra node attributes are supported:
|
||||
C(zbx_host) contains name of the host in Zabbix. Use this if desired type of map element is C(host).
|
||||
C(zbx_group) contains name of the host group in Zabbix. Use this if desired type of map element is C(host group).
|
||||
C(zbx_map) contains name of the map in Zabbix. Use this if desired type of map element is C(map).
|
||||
C(zbx_label) contains label of map element.
|
||||
C(zbx_image) contains name of the image used to display the element in default state.
|
||||
C(zbx_image_disabled) contains name of the image used to display disabled map element.
|
||||
C(zbx_image_maintenance) contains name of the image used to display map element in maintenance.
|
||||
C(zbx_image_problem) contains name of the image used to display map element with problems.
|
||||
C(zbx_url) contains map element URL in C(name:url) format.
|
||||
More than one URL could be specified by adding a postfix (e.g., C(zbx_url1), C(zbx_url2))."
|
||||
- "The following extra link attributes are supported:
|
||||
C(zbx_draw_style) contains link line draw style. Possible values: C(line), C(bold), C(dotted), C(dashed).
|
||||
C(zbx_trigger) contains name of the trigger used as a link indicator in C(host_name:trigger_name) format.
|
||||
More than one trigger could be specified by adding a postfix (e.g., C(zbx_trigger1), C(zbx_trigger2)).
|
||||
C(zbx_trigger_color) contains indicator color specified either as CSS3 name or as a hexadecimal code starting with C(#).
|
||||
C(zbx_trigger_draw_style) contains indicator draw style. Possible values are the same as for C(zbx_draw_style)."
|
||||
requirements:
|
||||
- "python >= 2.6"
|
||||
- "zabbix-api >= 0.5.4"
|
||||
- pydotplus
|
||||
- webcolors
|
||||
- Pillow
|
||||
- Graphviz
|
||||
options:
|
||||
name:
|
||||
description:
|
||||
- Name of the map.
|
||||
required: true
|
||||
aliases: [ "map_name" ]
|
||||
type: str
|
||||
data:
|
||||
description:
|
||||
- Graph written in DOT language.
|
||||
required: false
|
||||
aliases: [ "dot_data" ]
|
||||
type: str
|
||||
state:
|
||||
description:
|
||||
- State of the map.
|
||||
- On C(present), it will create if map does not exist or update the map if the associated data is different.
|
||||
- On C(absent) will remove the map if it exists.
|
||||
required: false
|
||||
choices: ['present', 'absent']
|
||||
default: "present"
|
||||
type: str
|
||||
width:
|
||||
description:
|
||||
- Width of the map.
|
||||
required: false
|
||||
default: 800
|
||||
type: int
|
||||
height:
|
||||
description:
|
||||
- Height of the map.
|
||||
required: false
|
||||
default: 600
|
||||
type: int
|
||||
margin:
|
||||
description:
|
||||
- Size of white space between map's borders and its elements.
|
||||
required: false
|
||||
default: 40
|
||||
type: int
|
||||
expand_problem:
|
||||
description:
|
||||
- Whether the problem trigger will be displayed for elements with a single problem.
|
||||
required: false
|
||||
type: bool
|
||||
default: true
|
||||
highlight:
|
||||
description:
|
||||
- Whether icon highlighting is enabled.
|
||||
required: false
|
||||
type: bool
|
||||
default: true
|
||||
label_type:
|
||||
description:
|
||||
- Map element label type.
|
||||
required: false
|
||||
choices: ['label', 'ip', 'name', 'status', 'nothing', 'custom']
|
||||
default: "name"
|
||||
type: str
|
||||
default_image:
|
||||
description:
|
||||
- Name of the Zabbix image used to display the element if this element doesn't have the C(zbx_image) attribute defined.
|
||||
required: false
|
||||
aliases: [ "image" ]
|
||||
type: str
|
||||
|
||||
extends_documentation_fragment:
|
||||
- community.general.zabbix
|
||||
|
||||
'''
|
||||
|
||||
RETURN = r''' # '''
|
||||
|
||||
EXAMPLES = r'''
|
||||
###
|
||||
### Example inventory:
|
||||
# [web]
|
||||
# web[01:03].example.com ansible_host=127.0.0.1
|
||||
# [db]
|
||||
# db.example.com ansible_host=127.0.0.1
|
||||
# [backup]
|
||||
# backup.example.com ansible_host=127.0.0.1
|
||||
###
|
||||
### Each inventory host is present in Zabbix with a matching name.
|
||||
###
|
||||
### Contents of 'map.j2':
|
||||
# digraph G {
|
||||
# graph [layout=dot splines=false overlap=scale]
|
||||
# INTERNET [zbx_url="Google:https://google.com" zbx_image="Cloud_(96)"]
|
||||
# {% for web_host in groups.web %}
|
||||
# {% set web_loop = loop %}
|
||||
# web{{ '%03d' % web_loop.index }} [zbx_host="{{ web_host }}"]
|
||||
# INTERNET -> web{{ '%03d' % web_loop.index }} [zbx_trigger="{{ web_host }}:Zabbix agent on {HOST.NAME} is unreachable for 5 minutes"]
|
||||
# {% for db_host in groups.db %}
|
||||
# {% set db_loop = loop %}
|
||||
# web{{ '%03d' % web_loop.index }} -> db{{ '%03d' % db_loop.index }}
|
||||
# {% endfor %}
|
||||
# {% endfor %}
|
||||
# { rank=same
|
||||
# {% for db_host in groups.db %}
|
||||
# {% set db_loop = loop %}
|
||||
# db{{ '%03d' % db_loop.index }} [zbx_host="{{ db_host }}"]
|
||||
# {% for backup_host in groups.backup %}
|
||||
# {% set backup_loop = loop %}
|
||||
# db{{ '%03d' % db_loop.index }} -> backup{{ '%03d' % backup_loop.index }} [color="blue"]
|
||||
# {% endfor %}
|
||||
# {% endfor %}
|
||||
# {% for backup_host in groups.backup %}
|
||||
# {% set backup_loop = loop %}
|
||||
# backup{{ '%03d' % backup_loop.index }} [zbx_host="{{ backup_host }}"]
|
||||
# {% endfor %}
|
||||
# }
|
||||
# }
|
||||
###
|
||||
### Create Zabbix map "Demo Map" made of template 'map.j2'
|
||||
- name: Create Zabbix map
|
||||
zabbix_map:
|
||||
server_url: http://zabbix.example.com
|
||||
login_user: username
|
||||
login_password: password
|
||||
name: Demo map
|
||||
state: present
|
||||
data: "{{ lookup('template', 'map.j2') }}"
|
||||
default_image: Server_(64)
|
||||
expand_problem: no
|
||||
highlight: no
|
||||
label_type: label
|
||||
delegate_to: localhost
|
||||
run_once: yes
|
||||
'''
|
||||
|
||||
ANSIBLE_METADATA = {
|
||||
'metadata_version': '1.1',
|
||||
'supported_by': 'community',
|
||||
'status': ['preview']
|
||||
}
|
||||
|
||||
|
||||
import atexit
|
||||
import base64
|
||||
import traceback
|
||||
|
||||
from io import BytesIO
|
||||
from operator import itemgetter
|
||||
from distutils.version import StrictVersion
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
|
||||
try:
|
||||
import pydotplus
|
||||
HAS_PYDOTPLUS = True
|
||||
except ImportError:
|
||||
PYDOT_IMP_ERR = traceback.format_exc()
|
||||
HAS_PYDOTPLUS = False
|
||||
|
||||
try:
|
||||
import webcolors
|
||||
HAS_WEBCOLORS = True
|
||||
except ImportError:
|
||||
WEBCOLORS_IMP_ERR = traceback.format_exc()
|
||||
HAS_WEBCOLORS = False
|
||||
|
||||
try:
|
||||
from zabbix_api import ZabbixAPI
|
||||
HAS_ZABBIX_API = True
|
||||
except ImportError:
|
||||
ZBX_IMP_ERR = traceback.format_exc()
|
||||
HAS_ZABBIX_API = False
|
||||
|
||||
try:
|
||||
from PIL import Image
|
||||
HAS_PIL = True
|
||||
except ImportError:
|
||||
PIL_IMP_ERR = traceback.format_exc()
|
||||
HAS_PIL = False
|
||||
|
||||
|
||||
class Map():
|
||||
def __init__(self, module, zbx):
|
||||
self._module = module
|
||||
self._zapi = zbx
|
||||
|
||||
self.map_name = module.params['name']
|
||||
self.dot_data = module.params['data']
|
||||
self.width = module.params['width']
|
||||
self.height = module.params['height']
|
||||
self.state = module.params['state']
|
||||
self.default_image = module.params['default_image']
|
||||
self.map_id = self._get_sysmap_id(self.map_name)
|
||||
self.margin = module.params['margin']
|
||||
self.expand_problem = module.params['expand_problem']
|
||||
self.highlight = module.params['highlight']
|
||||
self.label_type = module.params['label_type']
|
||||
self.api_version = self._zapi.api_version()
|
||||
self.selements_sort_keys = self._get_selements_sort_keys()
|
||||
|
||||
def _build_graph(self):
|
||||
try:
|
||||
graph_without_positions = pydotplus.graph_from_dot_data(self.dot_data)
|
||||
dot_data_with_positions = graph_without_positions.create_dot()
|
||||
graph_with_positions = pydotplus.graph_from_dot_data(dot_data_with_positions)
|
||||
if graph_with_positions:
|
||||
return graph_with_positions
|
||||
except Exception as e:
|
||||
self._module.fail_json(msg="Failed to build graph from DOT data: %s" % e)
|
||||
|
||||
def get_map_config(self):
|
||||
if not self.dot_data:
|
||||
self._module.fail_json(msg="'data' is mandatory with state 'present'")
|
||||
graph = self._build_graph()
|
||||
nodes = self._get_graph_nodes(graph)
|
||||
edges = self._get_graph_edges(graph)
|
||||
icon_ids = self._get_icon_ids()
|
||||
map_config = {
|
||||
'name': self.map_name,
|
||||
'label_type': self._get_label_type_id(self.label_type),
|
||||
'expandproblem': int(self.expand_problem),
|
||||
'highlight': int(self.highlight),
|
||||
'width': self.width,
|
||||
'height': self.height,
|
||||
'selements': self._get_selements(graph, nodes, icon_ids),
|
||||
'links': self._get_links(nodes, edges),
|
||||
}
|
||||
return map_config
|
||||
|
||||
def _get_label_type_id(self, label_type):
|
||||
label_type_ids = {
|
||||
'label': 0,
|
||||
'ip': 1,
|
||||
'name': 2,
|
||||
'status': 3,
|
||||
'nothing': 4,
|
||||
'custom': 5,
|
||||
}
|
||||
try:
|
||||
label_type_id = label_type_ids[label_type]
|
||||
except Exception as e:
|
||||
self._module.fail_json(msg="Failed to find id for label type '%s': %s" % (label_type, e))
|
||||
return label_type_id
|
||||
|
||||
def _get_images_info(self, data, icon_ids):
|
||||
images = [
|
||||
{
|
||||
'dot_tag': 'zbx_image',
|
||||
'zbx_property': 'iconid_off',
|
||||
'mandatory': True
|
||||
},
|
||||
{
|
||||
'dot_tag': 'zbx_image_disabled',
|
||||
'zbx_property': 'iconid_disabled',
|
||||
'mandatory': False
|
||||
},
|
||||
{
|
||||
'dot_tag': 'zbx_image_maintenance',
|
||||
'zbx_property': 'iconid_maintenance',
|
||||
'mandatory': False
|
||||
},
|
||||
{
|
||||
'dot_tag': 'zbx_image_problem',
|
||||
'zbx_property': 'iconid_on',
|
||||
'mandatory': False
|
||||
}
|
||||
]
|
||||
images_info = {}
|
||||
default_image = self.default_image if self.default_image else sorted(icon_ids.items())[0][0]
|
||||
for image in images:
|
||||
image_name = data.get(image['dot_tag'], None)
|
||||
if not image_name:
|
||||
if image['mandatory']:
|
||||
image_name = default_image
|
||||
else:
|
||||
continue
|
||||
image_name = remove_quotes(image_name)
|
||||
if image_name in icon_ids:
|
||||
images_info[image['zbx_property']] = icon_ids[image_name]
|
||||
if not image['mandatory']:
|
||||
images_info['use_iconmap'] = 0
|
||||
else:
|
||||
self._module.fail_json(msg="Failed to find id for image '%s'" % image_name)
|
||||
return images_info
|
||||
|
||||
def _get_element_type(self, data):
|
||||
types = {
|
||||
'host': 0,
|
||||
'sysmap': 1,
|
||||
'trigger': 2,
|
||||
'group': 3,
|
||||
'image': 4
|
||||
}
|
||||
element_type = {
|
||||
'elementtype': types['image'],
|
||||
}
|
||||
if StrictVersion(self.api_version) < StrictVersion('3.4'):
|
||||
element_type.update({
|
||||
'elementid': "0",
|
||||
})
|
||||
for type_name, type_id in sorted(types.items()):
|
||||
field_name = 'zbx_' + type_name
|
||||
if field_name in data:
|
||||
method_name = '_get_' + type_name + '_id'
|
||||
element_name = remove_quotes(data[field_name])
|
||||
get_element_id = getattr(self, method_name, None)
|
||||
if get_element_id:
|
||||
elementid = get_element_id(element_name)
|
||||
if elementid and int(elementid) > 0:
|
||||
element_type.update({
|
||||
'elementtype': type_id,
|
||||
'label': element_name
|
||||
})
|
||||
if StrictVersion(self.api_version) < StrictVersion('3.4'):
|
||||
element_type.update({
|
||||
'elementid': elementid,
|
||||
})
|
||||
else:
|
||||
element_type.update({
|
||||
'elements': [{
|
||||
type_name + 'id': elementid,
|
||||
}],
|
||||
})
|
||||
break
|
||||
else:
|
||||
self._module.fail_json(msg="Failed to find id for %s '%s'" % (type_name, element_name))
|
||||
return element_type
|
||||
|
||||
# get list of map elements (nodes)
|
||||
def _get_selements(self, graph, nodes, icon_ids):
|
||||
selements = []
|
||||
icon_sizes = {}
|
||||
scales = self._get_scales(graph)
|
||||
for selementid, (node, data) in enumerate(nodes.items(), start=1):
|
||||
selement = {
|
||||
'selementid': selementid
|
||||
}
|
||||
data['selementid'] = selementid
|
||||
|
||||
images_info = self._get_images_info(data, icon_ids)
|
||||
selement.update(images_info)
|
||||
image_id = images_info['iconid_off']
|
||||
if image_id not in icon_sizes:
|
||||
icon_sizes[image_id] = self._get_icon_size(image_id)
|
||||
|
||||
pos = self._convert_coordinates(data['pos'], scales, icon_sizes[image_id])
|
||||
selement.update(pos)
|
||||
|
||||
selement['label'] = remove_quotes(node)
|
||||
element_type = self._get_element_type(data)
|
||||
selement.update(element_type)
|
||||
|
||||
label = self._get_label(data)
|
||||
if label:
|
||||
selement['label'] = label
|
||||
|
||||
urls = self._get_urls(data)
|
||||
if urls:
|
||||
selement['urls'] = urls
|
||||
|
||||
selements.append(selement)
|
||||
return selements
|
||||
|
||||
def _get_links(self, nodes, edges):
|
||||
links = {}
|
||||
for edge in edges:
|
||||
link_id = tuple(sorted(edge.obj_dict['points']))
|
||||
node1, node2 = link_id
|
||||
data = edge.obj_dict['attributes']
|
||||
|
||||
if "style" in data and data['style'] == "invis":
|
||||
continue
|
||||
|
||||
if link_id not in links:
|
||||
links[link_id] = {
|
||||
'selementid1': min(nodes[node1]['selementid'], nodes[node2]['selementid']),
|
||||
'selementid2': max(nodes[node1]['selementid'], nodes[node2]['selementid']),
|
||||
}
|
||||
link = links[link_id]
|
||||
|
||||
if "color" not in link:
|
||||
link['color'] = self._get_color_hex(remove_quotes(data.get('color', 'green')))
|
||||
|
||||
if "zbx_draw_style" not in link:
|
||||
link['drawtype'] = self._get_link_draw_style_id(remove_quotes(data.get('zbx_draw_style', 'line')))
|
||||
|
||||
label = self._get_label(data)
|
||||
if label and "label" not in link:
|
||||
link['label'] = label
|
||||
|
||||
triggers = self._get_triggers(data)
|
||||
if triggers:
|
||||
if "linktriggers" not in link:
|
||||
link['linktriggers'] = []
|
||||
link['linktriggers'] += triggers
|
||||
|
||||
return list(links.values())
|
||||
|
||||
def _get_urls(self, data):
|
||||
urls = []
|
||||
for url_raw in [remove_quotes(value) for key, value in data.items() if key.startswith("zbx_url")]:
|
||||
try:
|
||||
name, url = url_raw.split(':', 1)
|
||||
except Exception as e:
|
||||
self._module.fail_json(msg="Failed to parse zbx_url='%s': %s" % (url_raw, e))
|
||||
urls.append({
|
||||
'name': name,
|
||||
'url': url,
|
||||
})
|
||||
return urls
|
||||
|
||||
def _get_triggers(self, data):
|
||||
triggers = []
|
||||
for trigger_definition in [remove_quotes(value) for key, value in data.items() if key.startswith("zbx_trigger")]:
|
||||
triggerid = self._get_trigger_id(trigger_definition)
|
||||
if triggerid:
|
||||
triggers.append({
|
||||
'triggerid': triggerid,
|
||||
'color': self._get_color_hex(remove_quotes(data.get('zbx_trigger_color', 'red'))),
|
||||
'drawtype': self._get_link_draw_style_id(remove_quotes(data.get('zbx_trigger_draw_style', 'bold'))),
|
||||
})
|
||||
else:
|
||||
self._module.fail_json(msg="Failed to find trigger '%s'" % (trigger_definition))
|
||||
return triggers
|
||||
|
||||
@staticmethod
|
||||
def _get_label(data, default=None):
|
||||
if "zbx_label" in data:
|
||||
label = remove_quotes(data['zbx_label']).replace('\\n', '\n')
|
||||
elif "label" in data:
|
||||
label = remove_quotes(data['label'])
|
||||
else:
|
||||
label = default
|
||||
return label
|
||||
|
||||
def _get_sysmap_id(self, map_name):
|
||||
exist_map = self._zapi.map.get({'filter': {'name': map_name}})
|
||||
if exist_map:
|
||||
return exist_map[0]['sysmapid']
|
||||
return None
|
||||
|
||||
def _get_group_id(self, group_name):
|
||||
exist_group = self._zapi.hostgroup.get({'filter': {'name': group_name}})
|
||||
if exist_group:
|
||||
return exist_group[0]['groupid']
|
||||
return None
|
||||
|
||||
def map_exists(self):
|
||||
return bool(self.map_id)
|
||||
|
||||
def create_map(self, map_config):
|
||||
try:
|
||||
if self._module.check_mode:
|
||||
self._module.exit_json(changed=True)
|
||||
result = self._zapi.map.create(map_config)
|
||||
if result:
|
||||
return result
|
||||
except Exception as e:
|
||||
self._module.fail_json(msg="Failed to create map: %s" % e)
|
||||
|
||||
def update_map(self, map_config):
|
||||
if not self.map_id:
|
||||
self._module.fail_json(msg="Failed to update map: map_id is unknown. Try to create_map instead.")
|
||||
try:
|
||||
if self._module.check_mode:
|
||||
self._module.exit_json(changed=True)
|
||||
map_config['sysmapid'] = self.map_id
|
||||
result = self._zapi.map.update(map_config)
|
||||
if result:
|
||||
return result
|
||||
except Exception as e:
|
||||
self._module.fail_json(msg="Failed to update map: %s" % e)
|
||||
|
||||
def delete_map(self):
|
||||
if not self.map_id:
|
||||
self._module.fail_json(msg="Failed to delete map: map_id is unknown.")
|
||||
try:
|
||||
if self._module.check_mode:
|
||||
self._module.exit_json(changed=True)
|
||||
self._zapi.map.delete([self.map_id])
|
||||
except Exception as e:
|
||||
self._module.fail_json(msg="Failed to delete map, Exception: %s" % e)
|
||||
|
||||
def is_exist_map_correct(self, generated_map_config):
|
||||
exist_map_configs = self._zapi.map.get({
|
||||
'sysmapids': self.map_id,
|
||||
'selectLinks': 'extend',
|
||||
'selectSelements': 'extend'
|
||||
})
|
||||
exist_map_config = exist_map_configs[0]
|
||||
if not self._is_dicts_equal(generated_map_config, exist_map_config):
|
||||
return False
|
||||
if not self._is_selements_equal(generated_map_config['selements'], exist_map_config['selements']):
|
||||
return False
|
||||
self._update_ids(generated_map_config, exist_map_config)
|
||||
if not self._is_links_equal(generated_map_config['links'], exist_map_config['links']):
|
||||
return False
|
||||
return True
|
||||
|
||||
def _get_selements_sort_keys(self):
|
||||
keys_to_sort = ['label']
|
||||
if StrictVersion(self.api_version) < StrictVersion('3.4'):
|
||||
keys_to_sort.insert(0, 'elementid')
|
||||
return keys_to_sort
|
||||
|
||||
def _is_selements_equal(self, generated_selements, exist_selements):
|
||||
if len(generated_selements) != len(exist_selements):
|
||||
return False
|
||||
generated_selements_sorted = sorted(generated_selements, key=itemgetter(*self.selements_sort_keys))
|
||||
exist_selements_sorted = sorted(exist_selements, key=itemgetter(*self.selements_sort_keys))
|
||||
for (generated_selement, exist_selement) in zip(generated_selements_sorted, exist_selements_sorted):
|
||||
if StrictVersion(self.api_version) >= StrictVersion("3.4"):
|
||||
if not self._is_elements_equal(generated_selement.get('elements', []), exist_selement.get('elements', [])):
|
||||
return False
|
||||
if not self._is_dicts_equal(generated_selement, exist_selement, ['selementid']):
|
||||
return False
|
||||
if not self._is_urls_equal(generated_selement.get('urls', []), exist_selement.get('urls', [])):
|
||||
return False
|
||||
return True
|
||||
|
||||
def _is_urls_equal(self, generated_urls, exist_urls):
|
||||
if len(generated_urls) != len(exist_urls):
|
||||
return False
|
||||
generated_urls_sorted = sorted(generated_urls, key=itemgetter('name', 'url'))
|
||||
exist_urls_sorted = sorted(exist_urls, key=itemgetter('name', 'url'))
|
||||
for (generated_url, exist_url) in zip(generated_urls_sorted, exist_urls_sorted):
|
||||
if not self._is_dicts_equal(generated_url, exist_url, ['selementid']):
|
||||
return False
|
||||
return True
|
||||
|
||||
def _is_elements_equal(self, generated_elements, exist_elements):
|
||||
if len(generated_elements) != len(exist_elements):
|
||||
return False
|
||||
generated_elements_sorted = sorted(generated_elements, key=lambda k: k.values()[0])
|
||||
exist_elements_sorted = sorted(exist_elements, key=lambda k: k.values()[0])
|
||||
for (generated_element, exist_element) in zip(generated_elements_sorted, exist_elements_sorted):
|
||||
if not self._is_dicts_equal(generated_element, exist_element, ['selementid']):
|
||||
return False
|
||||
return True
|
||||
|
||||
# since generated IDs differ from real Zabbix ones, make real IDs match generated ones
|
||||
def _update_ids(self, generated_map_config, exist_map_config):
|
||||
generated_selements_sorted = sorted(generated_map_config['selements'], key=itemgetter(*self.selements_sort_keys))
|
||||
exist_selements_sorted = sorted(exist_map_config['selements'], key=itemgetter(*self.selements_sort_keys))
|
||||
id_mapping = {}
|
||||
for (generated_selement, exist_selement) in zip(generated_selements_sorted, exist_selements_sorted):
|
||||
id_mapping[exist_selement['selementid']] = generated_selement['selementid']
|
||||
for link in exist_map_config['links']:
|
||||
link['selementid1'] = id_mapping[link['selementid1']]
|
||||
link['selementid2'] = id_mapping[link['selementid2']]
|
||||
if link['selementid2'] < link['selementid1']:
|
||||
link['selementid1'], link['selementid2'] = link['selementid2'], link['selementid1']
|
||||
|
||||
def _is_links_equal(self, generated_links, exist_links):
|
||||
if len(generated_links) != len(exist_links):
|
||||
return False
|
||||
generated_links_sorted = sorted(generated_links, key=itemgetter('selementid1', 'selementid2', 'color', 'drawtype'))
|
||||
exist_links_sorted = sorted(exist_links, key=itemgetter('selementid1', 'selementid2', 'color', 'drawtype'))
|
||||
for (generated_link, exist_link) in zip(generated_links_sorted, exist_links_sorted):
|
||||
if not self._is_dicts_equal(generated_link, exist_link, ['selementid1', 'selementid2']):
|
||||
return False
|
||||
if not self._is_triggers_equal(generated_link.get('linktriggers', []), exist_link.get('linktriggers', [])):
|
||||
return False
|
||||
return True
|
||||
|
||||
def _is_triggers_equal(self, generated_triggers, exist_triggers):
|
||||
if len(generated_triggers) != len(exist_triggers):
|
||||
return False
|
||||
generated_triggers_sorted = sorted(generated_triggers, key=itemgetter('triggerid'))
|
||||
exist_triggers_sorted = sorted(exist_triggers, key=itemgetter('triggerid'))
|
||||
for (generated_trigger, exist_trigger) in zip(generated_triggers_sorted, exist_triggers_sorted):
|
||||
if not self._is_dicts_equal(generated_trigger, exist_trigger):
|
||||
return False
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def _is_dicts_equal(d1, d2, exclude_keys=None):
|
||||
if exclude_keys is None:
|
||||
exclude_keys = []
|
||||
for key in d1.keys():
|
||||
if isinstance(d1[key], dict) or isinstance(d1[key], list):
|
||||
continue
|
||||
if key in exclude_keys:
|
||||
continue
|
||||
# compare as strings since Zabbix API returns everything as strings
|
||||
if key not in d2 or str(d2[key]) != str(d1[key]):
|
||||
return False
|
||||
return True
|
||||
|
||||
def _get_host_id(self, hostname):
|
||||
hostid = self._zapi.host.get({'filter': {'host': hostname}})
|
||||
if hostid:
|
||||
return str(hostid[0]['hostid'])
|
||||
|
||||
def _get_trigger_id(self, trigger_definition):
|
||||
try:
|
||||
host, trigger = trigger_definition.split(':', 1)
|
||||
except Exception as e:
|
||||
self._module.fail_json(msg="Failed to parse zbx_trigger='%s': %s" % (trigger_definition, e))
|
||||
triggerid = self._zapi.trigger.get({
|
||||
'host': host,
|
||||
'filter': {
|
||||
'description': trigger
|
||||
}
|
||||
})
|
||||
if triggerid:
|
||||
return str(triggerid[0]['triggerid'])
|
||||
|
||||
def _get_icon_ids(self):
|
||||
icons_list = self._zapi.image.get({})
|
||||
icon_ids = {}
|
||||
for icon in icons_list:
|
||||
icon_ids[icon['name']] = icon['imageid']
|
||||
return icon_ids
|
||||
|
||||
def _get_icon_size(self, icon_id):
|
||||
icons_list = self._zapi.image.get({
|
||||
'imageids': [
|
||||
icon_id
|
||||
],
|
||||
'select_image': True
|
||||
})
|
||||
if len(icons_list) > 0:
|
||||
icon_base64 = icons_list[0]['image']
|
||||
else:
|
||||
self._module.fail_json(msg="Failed to find image with id %s" % icon_id)
|
||||
image = Image.open(BytesIO(base64.b64decode(icon_base64)))
|
||||
icon_width, icon_height = image.size
|
||||
return icon_width, icon_height
|
||||
|
||||
@staticmethod
|
||||
def _get_node_attributes(node):
|
||||
attr = {}
|
||||
if "attributes" in node.obj_dict:
|
||||
attr.update(node.obj_dict['attributes'])
|
||||
pos = node.get_pos()
|
||||
if pos is not None:
|
||||
pos = remove_quotes(pos)
|
||||
xx, yy = pos.split(",")
|
||||
attr['pos'] = (float(xx), float(yy))
|
||||
return attr
|
||||
|
||||
def _get_graph_nodes(self, parent):
|
||||
nodes = {}
|
||||
for node in parent.get_nodes():
|
||||
node_name = node.get_name()
|
||||
if node_name in ('node', 'graph', 'edge'):
|
||||
continue
|
||||
nodes[node_name] = self._get_node_attributes(node)
|
||||
for subgraph in parent.get_subgraphs():
|
||||
nodes.update(self._get_graph_nodes(subgraph))
|
||||
return nodes
|
||||
|
||||
def _get_graph_edges(self, parent):
|
||||
edges = []
|
||||
for edge in parent.get_edges():
|
||||
edges.append(edge)
|
||||
for subgraph in parent.get_subgraphs():
|
||||
edges += self._get_graph_edges(subgraph)
|
||||
return edges
|
||||
|
||||
def _get_scales(self, graph):
|
||||
bb = remove_quotes(graph.get_bb())
|
||||
min_x, min_y, max_x, max_y = bb.split(",")
|
||||
scale_x = (self.width - self.margin * 2) / (float(max_x) - float(min_x)) if float(max_x) != float(min_x) else 0
|
||||
scale_y = (self.height - self.margin * 2) / (float(max_y) - float(min_y)) if float(max_y) != float(min_y) else 0
|
||||
return {
|
||||
'min_x': float(min_x),
|
||||
'min_y': float(min_y),
|
||||
'max_x': float(max_x),
|
||||
'max_y': float(max_y),
|
||||
'scale_x': float(scale_x),
|
||||
'scale_y': float(scale_y),
|
||||
}
|
||||
|
||||
# transform Graphviz coordinates to Zabbix's ones
|
||||
def _convert_coordinates(self, pos, scales, icon_size):
|
||||
return {
|
||||
'x': int((pos[0] - scales['min_x']) * scales['scale_x'] - icon_size[0] / 2 + self.margin),
|
||||
'y': int((scales['max_y'] - pos[1] + scales['min_y']) * scales['scale_y'] - icon_size[1] / 2 + self.margin),
|
||||
}
|
||||
|
||||
def _get_color_hex(self, color_name):
|
||||
if color_name.startswith('#'):
|
||||
color_hex = color_name
|
||||
else:
|
||||
try:
|
||||
color_hex = webcolors.name_to_hex(color_name)
|
||||
except Exception as e:
|
||||
self._module.fail_json(msg="Failed to get RGB hex for color '%s': %s" % (color_name, e))
|
||||
color_hex = color_hex.strip('#').upper()
|
||||
return color_hex
|
||||
|
||||
def _get_link_draw_style_id(self, draw_style):
|
||||
draw_style_ids = {
|
||||
'line': 0,
|
||||
'bold': 2,
|
||||
'dotted': 3,
|
||||
'dashed': 4
|
||||
}
|
||||
try:
|
||||
draw_style_id = draw_style_ids[draw_style]
|
||||
except Exception as e:
|
||||
self._module.fail_json(msg="Failed to find id for draw type '%s': %s" % (draw_style, e))
|
||||
return draw_style_id
|
||||
|
||||
|
||||
# If a string has single or double quotes around it, remove them.
|
||||
def remove_quotes(s):
|
||||
if (s[0] == s[-1]) and s.startswith(("'", '"')):
|
||||
s = s[1:-1]
|
||||
return s
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
server_url=dict(type='str', required=True, aliases=['url']),
|
||||
login_user=dict(type='str', required=True),
|
||||
login_password=dict(type='str', required=True, no_log=True),
|
||||
http_login_user=dict(type='str', required=False, default=None),
|
||||
http_login_password=dict(type='str', required=False, default=None, no_log=True),
|
||||
timeout=dict(type='int', default=10),
|
||||
validate_certs=dict(type='bool', required=False, default=True),
|
||||
name=dict(type='str', required=True, aliases=['map_name']),
|
||||
data=dict(type='str', required=False, aliases=['dot_data']),
|
||||
width=dict(type='int', default=800),
|
||||
height=dict(type='int', default=600),
|
||||
state=dict(type='str', default="present", choices=['present', 'absent']),
|
||||
default_image=dict(type='str', required=False, aliases=['image']),
|
||||
margin=dict(type='int', default=40),
|
||||
expand_problem=dict(type='bool', default=True),
|
||||
highlight=dict(type='bool', default=True),
|
||||
label_type=dict(type='str', default='name', choices=['label', 'ip', 'name', 'status', 'nothing', 'custom']),
|
||||
),
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
if not HAS_ZABBIX_API:
|
||||
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'), exception=ZBX_IMP_ERR)
|
||||
if not HAS_PYDOTPLUS:
|
||||
module.fail_json(msg=missing_required_lib('pydotplus', url='https://pypi.org/project/pydotplus/'), exception=PYDOT_IMP_ERR)
|
||||
if not HAS_WEBCOLORS:
|
||||
module.fail_json(msg=missing_required_lib('webcolors', url='https://pypi.org/project/webcolors/'), exception=WEBCOLORS_IMP_ERR)
|
||||
if not HAS_PIL:
|
||||
module.fail_json(msg=missing_required_lib('Pillow', url='https://pypi.org/project/Pillow/'), exception=PIL_IMP_ERR)
|
||||
|
||||
server_url = module.params['server_url']
|
||||
login_user = module.params['login_user']
|
||||
login_password = module.params['login_password']
|
||||
http_login_user = module.params['http_login_user']
|
||||
http_login_password = module.params['http_login_password']
|
||||
timeout = module.params['timeout']
|
||||
validate_certs = module.params['validate_certs']
|
||||
|
||||
zbx = None
|
||||
|
||||
# login to zabbix
|
||||
try:
|
||||
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
|
||||
validate_certs=validate_certs)
|
||||
zbx.login(login_user, login_password)
|
||||
atexit.register(zbx.logout)
|
||||
except Exception as e:
|
||||
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
|
||||
|
||||
sysmap = Map(module, zbx)
|
||||
|
||||
if sysmap.state == "absent":
|
||||
if sysmap.map_exists():
|
||||
sysmap.delete_map()
|
||||
module.exit_json(changed=True, result="Successfully deleted map: %s" % sysmap.map_name)
|
||||
else:
|
||||
module.exit_json(changed=False)
|
||||
else:
|
||||
map_config = sysmap.get_map_config()
|
||||
if sysmap.map_exists():
|
||||
if sysmap.is_exist_map_correct(map_config):
|
||||
module.exit_json(changed=False)
|
||||
else:
|
||||
sysmap.update_map(map_config)
|
||||
module.exit_json(changed=True, result="Successfully updated map: %s" % sysmap.map_name)
|
||||
else:
|
||||
sysmap.create_map(map_config)
|
||||
module.exit_json(changed=True, result="Successfully created map: %s" % sysmap.map_name)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1,705 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: zabbix_mediatype
|
||||
short_description: Create/Update/Delete Zabbix media types
|
||||
description:
|
||||
- This module allows you to create, modify and delete Zabbix media types.
|
||||
author:
|
||||
- Ruben Tsirunyan (@rubentsirunyan)
|
||||
requirements:
|
||||
- "zabbix-api >= 0.5.4"
|
||||
|
||||
options:
|
||||
name:
|
||||
type: 'str'
|
||||
description:
|
||||
- Name of the media type.
|
||||
required: true
|
||||
state:
|
||||
type: 'str'
|
||||
description:
|
||||
- Desired state of the mediatype.
|
||||
- On C(present), it will create a mediatype if it does not exist or update the mediatype if the associated data is different.
|
||||
- On C(absent), it will remove the mediatype if it exists.
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
default: 'present'
|
||||
type:
|
||||
type: 'str'
|
||||
description:
|
||||
- Type of the media type.
|
||||
- Media types I(jabber) and I(ez_texting) workable only with Zabbix 4.2 or less.
|
||||
choices:
|
||||
- email
|
||||
- script
|
||||
- sms
|
||||
- jabber
|
||||
- ez_texting
|
||||
required: true
|
||||
status:
|
||||
type: 'str'
|
||||
description:
|
||||
- Whether the media type is enabled or no.
|
||||
choices:
|
||||
- enabled
|
||||
- disabled
|
||||
default: 'enabled'
|
||||
max_sessions:
|
||||
type: 'int'
|
||||
description:
|
||||
- The maximum number of alerts that can be processed in parallel.
|
||||
- Possible value is 1 when I(type=sms) and 0-100 otherwise.
|
||||
default: 1
|
||||
max_attempts:
|
||||
type: 'int'
|
||||
description:
|
||||
- The maximum number of attempts to send an alert.
|
||||
- Possible range is 0-10
|
||||
default: 3
|
||||
attempt_interval:
|
||||
type: 'int'
|
||||
description:
|
||||
- The interval between retry attempts.
|
||||
- Possible range is 0-60
|
||||
default: 10
|
||||
script_name:
|
||||
type: 'str'
|
||||
description:
|
||||
- The name of the executed script.
|
||||
- Required when I(type=script).
|
||||
script_params:
|
||||
type: 'list'
|
||||
elements: str
|
||||
description:
|
||||
- List of script parameters.
|
||||
- Required when I(type=script).
|
||||
gsm_modem:
|
||||
type: 'str'
|
||||
description:
|
||||
- Serial device name of the gsm modem.
|
||||
- Required when I(type=sms).
|
||||
username:
|
||||
type: 'str'
|
||||
description:
|
||||
- Username or Jabber identifier.
|
||||
- Required when I(type=jabber) or I(type=ez_texting).
|
||||
- Required when I(type=email) and I(smtp_authentication=true).
|
||||
password:
|
||||
type: 'str'
|
||||
description:
|
||||
- Authentication password.
|
||||
- Required when I(type=jabber) or I(type=ez_texting).
|
||||
- Required when I(type=email) and I(smtp_authentication=true).
|
||||
smtp_server:
|
||||
type: 'str'
|
||||
description:
|
||||
- SMTP server host.
|
||||
- Required when I(type=email).
|
||||
default: 'localhost'
|
||||
smtp_server_port:
|
||||
type: 'int'
|
||||
description:
|
||||
- SMTP server port.
|
||||
- Required when I(type=email).
|
||||
default: 25
|
||||
smtp_helo:
|
||||
type: 'str'
|
||||
description:
|
||||
- SMTP HELO.
|
||||
- Required when I(type=email).
|
||||
default: 'localhost'
|
||||
smtp_email:
|
||||
type: 'str'
|
||||
description:
|
||||
- Email address from which notifications will be sent.
|
||||
- Required when I(type=email).
|
||||
smtp_authentication:
|
||||
type: 'bool'
|
||||
description:
|
||||
- Whether SMTP authentication with username and password should be enabled or not.
|
||||
- If set to C(true), C(username) and C(password) should be specified.
|
||||
default: false
|
||||
smtp_security:
|
||||
type: 'str'
|
||||
description:
|
||||
- SMTP connection security level to use.
|
||||
choices:
|
||||
- None
|
||||
- STARTTLS
|
||||
- SSL/TLS
|
||||
smtp_verify_host:
|
||||
type: 'bool'
|
||||
description:
|
||||
- SSL verify host for SMTP.
|
||||
- Can be specified when I(smtp_security=STARTTLS) or I(smtp_security=SSL/TLS)
|
||||
default: false
|
||||
smtp_verify_peer:
|
||||
type: 'bool'
|
||||
description:
|
||||
- SSL verify peer for SMTP.
|
||||
- Can be specified when I(smtp_security=STARTTLS) or I(smtp_security=SSL/TLS)
|
||||
default: false
|
||||
message_text_limit:
|
||||
type: 'str'
|
||||
description:
|
||||
- The message text limit.
|
||||
- Required when I(type=ez_texting).
|
||||
- 160 characters for USA and 136 characters for Canada.
|
||||
choices:
|
||||
- USA
|
||||
- Canada
|
||||
extends_documentation_fragment:
|
||||
- community.general.zabbix
|
||||
|
||||
|
||||
'''
|
||||
|
||||
RETURN = r''' # '''
|
||||
|
||||
EXAMPLES = r'''
|
||||
- name: 'Create an email mediatype with SMTP authentication'
|
||||
zabbix_mediatype:
|
||||
name: "Ops email"
|
||||
server_url: "http://example.com/zabbix/"
|
||||
login_user: Admin
|
||||
login_password: "zabbix"
|
||||
type: 'email'
|
||||
smtp_server: 'example.com'
|
||||
smtp_server_port: 2000
|
||||
smtp_email: 'ops@example.com'
|
||||
smtp_authentication: true
|
||||
username: 'smtp_user'
|
||||
password: 'smtp_pass'
|
||||
|
||||
- name: 'Create a script mediatype'
|
||||
zabbix_mediatype:
|
||||
name: "my script"
|
||||
server_url: "http://example.com/zabbix/"
|
||||
login_user: Admin
|
||||
login_password: "zabbix"
|
||||
type: 'script'
|
||||
script_name: 'my_script.py'
|
||||
script_params:
|
||||
- 'arg1'
|
||||
- 'arg2'
|
||||
|
||||
- name: 'Create a jabber mediatype'
|
||||
zabbix_mediatype:
|
||||
name: "My jabber"
|
||||
server_url: "http://example.com/zabbix/"
|
||||
login_user: Admin
|
||||
login_password: "zabbix"
|
||||
type: 'jabber'
|
||||
username: 'jabber_id'
|
||||
password: 'jabber_pass'
|
||||
|
||||
- name: 'Create an SMS mediatype'
|
||||
zabbix_mediatype:
|
||||
name: "My SMS Mediatype"
|
||||
server_url: "http://example.com/zabbix/"
|
||||
login_user: Admin
|
||||
login_password: "zabbix"
|
||||
type: 'sms'
|
||||
gsm_modem: '/dev/ttyS0'
|
||||
'''
|
||||
|
||||
|
||||
import atexit
|
||||
import traceback
|
||||
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
from distutils.version import LooseVersion
|
||||
|
||||
|
||||
try:
|
||||
from zabbix_api import ZabbixAPI
|
||||
HAS_ZABBIX_API = True
|
||||
except ImportError:
|
||||
ZBX_IMP_ERR = traceback.format_exc()
|
||||
HAS_ZABBIX_API = False
|
||||
|
||||
|
||||
def to_numeric_value(value, strs):
|
||||
return strs.get(value)
|
||||
|
||||
|
||||
def validate_params(module, params):
|
||||
"""Validates arguments that are required together.
|
||||
|
||||
Fails the module with the message that shows the missing
|
||||
requirements if there are some.
|
||||
|
||||
Args:
|
||||
module: AnsibleModule object.
|
||||
params (list): Each element of this list
|
||||
is a list like
|
||||
['argument_key', 'argument_value', ['required_arg_1',
|
||||
'required_arg_2']].
|
||||
Format is the same as `required_if` parameter of AnsibleModule.
|
||||
"""
|
||||
for param in params:
|
||||
if module.params[param[0]] == param[1]:
|
||||
if None in [module.params[i] for i in param[2]]:
|
||||
module.fail_json(
|
||||
msg="Following arguments are required when {key} is {value}: {arguments}".format(
|
||||
key=param[0],
|
||||
value=param[1],
|
||||
arguments=', '.join(param[2])
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def construct_parameters(**kwargs):
|
||||
"""Translates data to a format suitable for Zabbix API and filters
|
||||
the ones that are related to the specified mediatype type.
|
||||
|
||||
Args:
|
||||
**kwargs: Arguments passed to the module.
|
||||
|
||||
Returns:
|
||||
A dictionary of arguments that are related to kwargs['transport_type'],
|
||||
and are in a format that is understandable by Zabbix API.
|
||||
"""
|
||||
if kwargs['transport_type'] == 'email':
|
||||
return dict(
|
||||
description=kwargs['name'],
|
||||
status=to_numeric_value(kwargs['status'],
|
||||
{'enabled': '0',
|
||||
'disabled': '1'}),
|
||||
type=to_numeric_value(kwargs['transport_type'],
|
||||
{'email': '0',
|
||||
'script': '1',
|
||||
'sms': '2',
|
||||
'jabber': '3',
|
||||
'ez_texting': '100'}),
|
||||
maxsessions=str(kwargs['max_sessions']),
|
||||
maxattempts=str(kwargs['max_attempts']),
|
||||
attempt_interval=str(kwargs['attempt_interval']),
|
||||
smtp_server=kwargs['smtp_server'],
|
||||
smtp_port=str(kwargs['smtp_server_port']),
|
||||
smtp_helo=kwargs['smtp_helo'],
|
||||
smtp_email=kwargs['smtp_email'],
|
||||
smtp_security=to_numeric_value(str(kwargs['smtp_security']),
|
||||
{'None': '0',
|
||||
'STARTTLS': '1',
|
||||
'SSL/TLS': '2'}),
|
||||
smtp_authentication=to_numeric_value(str(kwargs['smtp_authentication']),
|
||||
{'False': '0',
|
||||
'True': '1'}),
|
||||
smtp_verify_host=to_numeric_value(str(kwargs['smtp_verify_host']),
|
||||
{'False': '0',
|
||||
'True': '1'}),
|
||||
smtp_verify_peer=to_numeric_value(str(kwargs['smtp_verify_peer']),
|
||||
{'False': '0',
|
||||
'True': '1'}),
|
||||
username=kwargs['username'],
|
||||
passwd=kwargs['password']
|
||||
)
|
||||
|
||||
elif kwargs['transport_type'] == 'script':
|
||||
if kwargs['script_params'] is None:
|
||||
_script_params = '' # ZBX-15706
|
||||
else:
|
||||
_script_params = '\n'.join(str(i) for i in kwargs['script_params']) + '\n'
|
||||
return dict(
|
||||
description=kwargs['name'],
|
||||
status=to_numeric_value(kwargs['status'],
|
||||
{'enabled': '0',
|
||||
'disabled': '1'}),
|
||||
type=to_numeric_value(kwargs['transport_type'],
|
||||
{'email': '0',
|
||||
'script': '1',
|
||||
'sms': '2',
|
||||
'jabber': '3',
|
||||
'ez_texting': '100'}),
|
||||
maxsessions=str(kwargs['max_sessions']),
|
||||
maxattempts=str(kwargs['max_attempts']),
|
||||
attempt_interval=str(kwargs['attempt_interval']),
|
||||
exec_path=kwargs['script_name'],
|
||||
exec_params=_script_params
|
||||
)
|
||||
elif kwargs['transport_type'] == 'sms':
|
||||
return dict(
|
||||
description=kwargs['name'],
|
||||
status=to_numeric_value(kwargs['status'],
|
||||
{'enabled': '0',
|
||||
'disabled': '1'}),
|
||||
type=to_numeric_value(kwargs['transport_type'],
|
||||
{'email': '0',
|
||||
'script': '1',
|
||||
'sms': '2',
|
||||
'jabber': '3',
|
||||
'ez_texting': '100'}),
|
||||
maxsessions=str(kwargs['max_sessions']),
|
||||
maxattempts=str(kwargs['max_attempts']),
|
||||
attempt_interval=str(kwargs['attempt_interval']),
|
||||
gsm_modem=kwargs['gsm_modem']
|
||||
)
|
||||
elif kwargs['transport_type'] == 'jabber' and LooseVersion(kwargs['zbx_api_version']) <= LooseVersion('4.2'):
|
||||
return dict(
|
||||
description=kwargs['name'],
|
||||
status=to_numeric_value(kwargs['status'],
|
||||
{'enabled': '0',
|
||||
'disabled': '1'}),
|
||||
type=to_numeric_value(kwargs['transport_type'],
|
||||
{'email': '0',
|
||||
'script': '1',
|
||||
'sms': '2',
|
||||
'jabber': '3',
|
||||
'ez_texting': '100'}),
|
||||
maxsessions=str(kwargs['max_sessions']),
|
||||
maxattempts=str(kwargs['max_attempts']),
|
||||
attempt_interval=str(kwargs['attempt_interval']),
|
||||
username=kwargs['username'],
|
||||
passwd=kwargs['password']
|
||||
)
|
||||
elif kwargs['transport_type'] == 'ez_texting' and LooseVersion(kwargs['zbx_api_version']) <= LooseVersion('4.2'):
|
||||
return dict(
|
||||
description=kwargs['name'],
|
||||
status=to_numeric_value(kwargs['status'],
|
||||
{'enabled': '0',
|
||||
'disabled': '1'}),
|
||||
type=to_numeric_value(kwargs['transport_type'],
|
||||
{'email': '0',
|
||||
'script': '1',
|
||||
'sms': '2',
|
||||
'jabber': '3',
|
||||
'ez_texting': '100'}),
|
||||
maxsessions=str(kwargs['max_sessions']),
|
||||
maxattempts=str(kwargs['max_attempts']),
|
||||
attempt_interval=str(kwargs['attempt_interval']),
|
||||
username=kwargs['username'],
|
||||
passwd=kwargs['password'],
|
||||
exec_path=to_numeric_value(kwargs['message_text_limit'],
|
||||
{'USA': '0',
|
||||
'Canada': '1'}),
|
||||
)
|
||||
|
||||
return {'unsupported_parameter': kwargs['transport_type'], 'zbx_api_version': kwargs['zbx_api_version']}
|
||||
|
||||
|
||||
def check_if_mediatype_exists(module, zbx, name, zbx_api_version):
|
||||
"""Checks if mediatype exists.
|
||||
|
||||
Args:
|
||||
module: AnsibleModule object
|
||||
zbx: ZabbixAPI object
|
||||
name: Zabbix mediatype name
|
||||
|
||||
Returns:
|
||||
Tuple of (True, `id of the mediatype`) if mediatype exists, (False, None) otherwise
|
||||
"""
|
||||
filter_key_name = 'description'
|
||||
if LooseVersion(zbx_api_version) >= LooseVersion('4.4'):
|
||||
# description key changed to name key from zabbix 4.4
|
||||
filter_key_name = 'name'
|
||||
|
||||
try:
|
||||
mediatype_list = zbx.mediatype.get({
|
||||
'output': 'extend',
|
||||
'filter': {filter_key_name: [name]}
|
||||
})
|
||||
if len(mediatype_list) < 1:
|
||||
return False, None
|
||||
else:
|
||||
return True, mediatype_list[0]['mediatypeid']
|
||||
except Exception as e:
|
||||
module.fail_json(msg="Failed to get ID of the mediatype '{name}': {e}".format(name=name, e=e))
|
||||
|
||||
|
||||
def diff(existing, new):
|
||||
"""Constructs the diff for Ansible's --diff option.
|
||||
|
||||
Args:
|
||||
existing (dict): Existing mediatype data.
|
||||
new (dict): New mediatype data.
|
||||
|
||||
Returns:
|
||||
A dictionary like {'before': existing, 'after': new}
|
||||
with filtered empty values.
|
||||
"""
|
||||
before = {}
|
||||
after = {}
|
||||
for key in new:
|
||||
before[key] = existing[key]
|
||||
if new[key] is None:
|
||||
after[key] = ''
|
||||
else:
|
||||
after[key] = new[key]
|
||||
return {'before': before, 'after': after}
|
||||
|
||||
|
||||
def get_update_params(module, zbx, mediatype_id, **kwargs):
|
||||
"""Filters only the parameters that are different and need to be updated.
|
||||
|
||||
Args:
|
||||
module: AnsibleModule object.
|
||||
zbx: ZabbixAPI object.
|
||||
mediatype_id (int): ID of the mediatype to be updated.
|
||||
**kwargs: Parameters for the new mediatype.
|
||||
|
||||
Returns:
|
||||
A tuple where the first element is a dictionary of parameters
|
||||
that need to be updated and the second one is a dictionary
|
||||
returned by diff() function with
|
||||
existing mediatype data and new params passed to it.
|
||||
"""
|
||||
existing_mediatype = zbx.mediatype.get({
|
||||
'output': 'extend',
|
||||
'mediatypeids': [mediatype_id]
|
||||
})[0]
|
||||
|
||||
if existing_mediatype['type'] != kwargs['type']:
|
||||
return kwargs, diff(existing_mediatype, kwargs)
|
||||
else:
|
||||
params_to_update = {}
|
||||
for key in kwargs:
|
||||
if (not (kwargs[key] is None and existing_mediatype[key] == '')) and kwargs[key] != existing_mediatype[key]:
|
||||
params_to_update[key] = kwargs[key]
|
||||
return params_to_update, diff(existing_mediatype, kwargs)
|
||||
|
||||
|
||||
def delete_mediatype(module, zbx, mediatype_id):
|
||||
try:
|
||||
return zbx.mediatype.delete([mediatype_id])
|
||||
except Exception as e:
|
||||
module.fail_json(msg="Failed to delete mediatype '{_id}': {e}".format(_id=mediatype_id, e=e))
|
||||
|
||||
|
||||
def update_mediatype(module, zbx, **kwargs):
|
||||
try:
|
||||
mediatype_id = zbx.mediatype.update(kwargs)
|
||||
except Exception as e:
|
||||
module.fail_json(msg="Failed to update mediatype '{_id}': {e}".format(_id=kwargs['mediatypeid'], e=e))
|
||||
|
||||
|
||||
def create_mediatype(module, zbx, **kwargs):
|
||||
try:
|
||||
mediatype_id = zbx.mediatype.create(kwargs)
|
||||
except Exception as e:
|
||||
module.fail_json(msg="Failed to create mediatype '{name}': {e}".format(name=kwargs['description'], e=e))
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = dict(
|
||||
server_url=dict(type='str', required=True, aliases=['url']),
|
||||
login_user=dict(type='str', required=True),
|
||||
login_password=dict(type='str', required=True, no_log=True),
|
||||
http_login_user=dict(type='str', required=False, default=None),
|
||||
http_login_password=dict(type='str', required=False, default=None, no_log=True),
|
||||
validate_certs=dict(type='bool', required=False, default=True), timeout=dict(type='int', default=10),
|
||||
name=dict(type='str', required=True),
|
||||
state=dict(type='str', default='present', choices=['present', 'absent']),
|
||||
type=dict(type='str', choices=['email', 'script', 'sms', 'jabber', 'ez_texting'], required=True),
|
||||
status=dict(type='str', default='enabled', choices=['enabled', 'disabled'], required=False),
|
||||
max_sessions=dict(type='int', default=1, required=False),
|
||||
max_attempts=dict(type='int', default=3, required=False),
|
||||
attempt_interval=dict(type='int', default=10, required=False),
|
||||
# Script
|
||||
script_name=dict(type='str', required=False),
|
||||
script_params=dict(type='list', required=False),
|
||||
# SMS
|
||||
gsm_modem=dict(type='str', required=False),
|
||||
# Jabber
|
||||
username=dict(type='str', required=False),
|
||||
password=dict(type='str', required=False, no_log=True),
|
||||
# Email
|
||||
smtp_server=dict(type='str', default='localhost', required=False),
|
||||
smtp_server_port=dict(type='int', default=25, required=False),
|
||||
smtp_helo=dict(type='str', default='localhost', required=False),
|
||||
smtp_email=dict(type='str', required=False),
|
||||
smtp_security=dict(type='str', required=False, choices=['None', 'STARTTLS', 'SSL/TLS']),
|
||||
smtp_authentication=dict(type='bool', default=False, required=False),
|
||||
smtp_verify_host=dict(type='bool', default=False, required=False),
|
||||
smtp_verify_peer=dict(type='bool', default=False, required=False),
|
||||
# EZ Text
|
||||
message_text_limit=dict(type='str', required=False, choices=['USA', 'Canada'])
|
||||
)
|
||||
|
||||
required_params = [
|
||||
['type', 'email', ['smtp_email']],
|
||||
['type', 'script', ['script_name']],
|
||||
['type', 'sms', ['gsm_modem']],
|
||||
['type', 'jabber', ['username', 'password']],
|
||||
['type', 'ez_texting', ['username', 'password', 'message_text_limit']],
|
||||
['smtp_authentication', True, ['username', 'password']]
|
||||
]
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec=argument_spec,
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
if module.params['state'] == 'present':
|
||||
validate_params(module, required_params)
|
||||
|
||||
if not HAS_ZABBIX_API:
|
||||
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'), exception=ZBX_IMP_ERR)
|
||||
|
||||
server_url = module.params['server_url']
|
||||
login_user = module.params['login_user']
|
||||
login_password = module.params['login_password']
|
||||
http_login_user = module.params['http_login_user']
|
||||
http_login_password = module.params['http_login_password']
|
||||
validate_certs = module.params['validate_certs']
|
||||
state = module.params['state']
|
||||
timeout = module.params['timeout']
|
||||
name = module.params['name']
|
||||
transport_type = module.params['type']
|
||||
status = module.params['status']
|
||||
max_sessions = module.params['max_sessions']
|
||||
max_attempts = module.params['max_attempts']
|
||||
attempt_interval = module.params['attempt_interval']
|
||||
# Script
|
||||
script_name = module.params['script_name']
|
||||
script_params = module.params['script_params']
|
||||
# SMS
|
||||
gsm_modem = module.params['gsm_modem']
|
||||
# Jabber
|
||||
username = module.params['username']
|
||||
password = module.params['password']
|
||||
# Email
|
||||
smtp_server = module.params['smtp_server']
|
||||
smtp_server_port = module.params['smtp_server_port']
|
||||
smtp_helo = module.params['smtp_helo']
|
||||
smtp_email = module.params['smtp_email']
|
||||
smtp_security = module.params['smtp_security']
|
||||
smtp_authentication = module.params['smtp_authentication']
|
||||
smtp_verify_host = module.params['smtp_verify_host']
|
||||
smtp_verify_peer = module.params['smtp_verify_peer']
|
||||
# EZ Text
|
||||
message_text_limit = module.params['message_text_limit']
|
||||
|
||||
zbx = None
|
||||
|
||||
# login to zabbix
|
||||
try:
|
||||
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
|
||||
validate_certs=validate_certs)
|
||||
zbx.login(login_user, login_password)
|
||||
atexit.register(zbx.logout)
|
||||
except Exception as e:
|
||||
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
|
||||
|
||||
zbx_api_version = zbx.api_version()[:3]
|
||||
mediatype_exists, mediatype_id = check_if_mediatype_exists(module, zbx, name, zbx_api_version)
|
||||
|
||||
parameters = construct_parameters(
|
||||
name=name,
|
||||
transport_type=transport_type,
|
||||
status=status,
|
||||
max_sessions=max_sessions,
|
||||
max_attempts=max_attempts,
|
||||
attempt_interval=attempt_interval,
|
||||
script_name=script_name,
|
||||
script_params=script_params,
|
||||
gsm_modem=gsm_modem,
|
||||
username=username,
|
||||
password=password,
|
||||
smtp_server=smtp_server,
|
||||
smtp_server_port=smtp_server_port,
|
||||
smtp_helo=smtp_helo,
|
||||
smtp_email=smtp_email,
|
||||
smtp_security=smtp_security,
|
||||
smtp_authentication=smtp_authentication,
|
||||
smtp_verify_host=smtp_verify_host,
|
||||
smtp_verify_peer=smtp_verify_peer,
|
||||
message_text_limit=message_text_limit,
|
||||
zbx_api_version=zbx_api_version
|
||||
)
|
||||
|
||||
if 'unsupported_parameter' in parameters:
|
||||
module.fail_json(msg="%s is unsupported for Zabbix version %s" % (parameters['unsupported_parameter'], parameters['zbx_api_version']))
|
||||
|
||||
if LooseVersion(zbx_api_version) >= LooseVersion('4.4'):
|
||||
# description key changed to name key from zabbix 4.4
|
||||
parameters['name'] = parameters.pop('description')
|
||||
|
||||
if mediatype_exists:
|
||||
if state == 'absent':
|
||||
if module.check_mode:
|
||||
module.exit_json(
|
||||
changed=True,
|
||||
msg="Mediatype would have been deleted. Name: {name}, ID: {_id}".format(
|
||||
name=name,
|
||||
_id=mediatype_id
|
||||
)
|
||||
)
|
||||
mediatype_id = delete_mediatype(module, zbx, mediatype_id)
|
||||
module.exit_json(
|
||||
changed=True,
|
||||
msg="Mediatype deleted. Name: {name}, ID: {_id}".format(
|
||||
name=name,
|
||||
_id=mediatype_id
|
||||
)
|
||||
)
|
||||
else:
|
||||
params_to_update, diff = get_update_params(module, zbx, mediatype_id, **parameters)
|
||||
if params_to_update == {}:
|
||||
module.exit_json(
|
||||
changed=False,
|
||||
msg="Mediatype is up to date: {name}".format(name=name)
|
||||
)
|
||||
else:
|
||||
if module.check_mode:
|
||||
module.exit_json(
|
||||
changed=True,
|
||||
diff=diff,
|
||||
msg="Mediatype would have been updated. Name: {name}, ID: {_id}".format(
|
||||
name=name,
|
||||
_id=mediatype_id
|
||||
)
|
||||
)
|
||||
mediatype_id = update_mediatype(
|
||||
module, zbx,
|
||||
mediatypeid=mediatype_id,
|
||||
**params_to_update
|
||||
)
|
||||
module.exit_json(
|
||||
changed=True,
|
||||
diff=diff,
|
||||
msg="Mediatype updated. Name: {name}, ID: {_id}".format(
|
||||
name=name,
|
||||
_id=mediatype_id
|
||||
)
|
||||
)
|
||||
else:
|
||||
if state == "absent":
|
||||
module.exit_json(changed=False)
|
||||
else:
|
||||
if module.check_mode:
|
||||
module.exit_json(
|
||||
changed=True,
|
||||
msg="Mediatype would have been created. Name: {name}, ID: {_id}".format(
|
||||
name=name,
|
||||
_id=mediatype_id
|
||||
)
|
||||
)
|
||||
mediatype_id = create_mediatype(module, zbx, **parameters)
|
||||
module.exit_json(
|
||||
changed=True,
|
||||
msg="Mediatype created: {name}, ID: {_id}".format(
|
||||
name=name,
|
||||
_id=mediatype_id
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1,471 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
# (c) 2017, Alen Komic
|
||||
#
|
||||
# This file is part of Ansible
|
||||
#
|
||||
# Ansible is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Ansible is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: zabbix_proxy
|
||||
short_description: Create/delete/get/update Zabbix proxies
|
||||
description:
|
||||
- This module allows you to create, modify, get and delete Zabbix proxy entries.
|
||||
author:
|
||||
- "Alen Komic (@akomic)"
|
||||
requirements:
|
||||
- "python >= 2.6"
|
||||
- "zabbix-api >= 0.5.4"
|
||||
options:
|
||||
proxy_name:
|
||||
description:
|
||||
- Name of the proxy in Zabbix.
|
||||
required: true
|
||||
type: str
|
||||
proxy_address:
|
||||
description:
|
||||
- Comma-delimited list of IP/CIDR addresses or DNS names to accept active proxy requests from.
|
||||
- Requires I(status=active).
|
||||
- Works only with >= Zabbix 4.0. ( remove option for <= 4.0 )
|
||||
required: false
|
||||
type: str
|
||||
description:
|
||||
description:
|
||||
- Description of the proxy.
|
||||
required: false
|
||||
type: str
|
||||
status:
|
||||
description:
|
||||
- Type of proxy. (4 - active, 5 - passive)
|
||||
required: false
|
||||
choices: ['active', 'passive']
|
||||
default: "active"
|
||||
type: str
|
||||
tls_connect:
|
||||
description:
|
||||
- Connections to proxy.
|
||||
required: false
|
||||
choices: ['no_encryption','PSK','certificate']
|
||||
default: 'no_encryption'
|
||||
type: str
|
||||
tls_accept:
|
||||
description:
|
||||
- Connections from proxy.
|
||||
required: false
|
||||
choices: ['no_encryption','PSK','certificate']
|
||||
default: 'no_encryption'
|
||||
type: str
|
||||
ca_cert:
|
||||
description:
|
||||
- Certificate issuer.
|
||||
required: false
|
||||
aliases: [ tls_issuer ]
|
||||
type: str
|
||||
tls_subject:
|
||||
description:
|
||||
- Certificate subject.
|
||||
required: false
|
||||
type: str
|
||||
tls_psk_identity:
|
||||
description:
|
||||
- PSK identity. Required if either I(tls_connect) or I(tls_accept) has PSK enabled.
|
||||
required: false
|
||||
type: str
|
||||
tls_psk:
|
||||
description:
|
||||
- The preshared key, at least 32 hex digits. Required if either I(tls_connect) or I(tls_accept) has PSK enabled.
|
||||
required: false
|
||||
type: str
|
||||
state:
|
||||
description:
|
||||
- State of the proxy.
|
||||
- On C(present), it will create if proxy does not exist or update the proxy if the associated data is different.
|
||||
- On C(absent) will remove a proxy if it exists.
|
||||
required: false
|
||||
choices: ['present', 'absent']
|
||||
default: "present"
|
||||
type: str
|
||||
interface:
|
||||
description:
|
||||
- Dictionary with params for the interface when proxy is in passive mode.
|
||||
- For more information, review proxy interface documentation at
|
||||
- U(https://www.zabbix.com/documentation/4.0/manual/api/reference/proxy/object#proxy_interface).
|
||||
required: false
|
||||
suboptions:
|
||||
useip:
|
||||
type: int
|
||||
description:
|
||||
- Connect to proxy interface with IP address instead of DNS name.
|
||||
- 0 (don't use ip), 1 (use ip).
|
||||
default: 0
|
||||
choices: [0, 1]
|
||||
ip:
|
||||
type: str
|
||||
description:
|
||||
- IP address used by proxy interface.
|
||||
- Required if I(useip=1).
|
||||
default: ''
|
||||
dns:
|
||||
type: str
|
||||
description:
|
||||
- DNS name of the proxy interface.
|
||||
- Required if I(useip=0).
|
||||
default: ''
|
||||
port:
|
||||
type: str
|
||||
description:
|
||||
- Port used by proxy interface.
|
||||
default: '10051'
|
||||
type:
|
||||
type: int
|
||||
description:
|
||||
- Interface type to add.
|
||||
- This suboption is currently ignored for Zabbix proxy.
|
||||
- This suboption is deprecated since Ansible 2.10 and will eventually be removed in 2.14.
|
||||
required: false
|
||||
default: 0
|
||||
main:
|
||||
type: int
|
||||
description:
|
||||
- Whether the interface is used as default.
|
||||
- This suboption is currently ignored for Zabbix proxy.
|
||||
- This suboption is deprecated since Ansible 2.10 and will eventually be removed in 2.14.
|
||||
required: false
|
||||
default: 0
|
||||
default: {}
|
||||
type: dict
|
||||
|
||||
extends_documentation_fragment:
|
||||
- community.general.zabbix
|
||||
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
- name: Create or update a proxy with proxy type active
|
||||
local_action:
|
||||
module: zabbix_proxy
|
||||
server_url: http://monitor.example.com
|
||||
login_user: username
|
||||
login_password: password
|
||||
proxy_name: ExampleProxy
|
||||
description: ExampleProxy
|
||||
status: active
|
||||
state: present
|
||||
proxy_address: ExampleProxy.local
|
||||
|
||||
- name: Create a new passive proxy using only it's IP
|
||||
local_action:
|
||||
module: zabbix_proxy
|
||||
server_url: http://monitor.example.com
|
||||
login_user: username
|
||||
login_password: password
|
||||
proxy_name: ExampleProxy
|
||||
description: ExampleProxy
|
||||
status: passive
|
||||
state: present
|
||||
interface:
|
||||
useip: 1
|
||||
ip: 10.1.1.2
|
||||
port: 10051
|
||||
|
||||
- name: Create a new passive proxy using only it's DNS
|
||||
local_action:
|
||||
module: zabbix_proxy
|
||||
server_url: http://monitor.example.com
|
||||
login_user: username
|
||||
login_password: password
|
||||
proxy_name: ExampleProxy
|
||||
description: ExampleProxy
|
||||
status: passive
|
||||
state: present
|
||||
interface:
|
||||
dns: proxy.example.com
|
||||
port: 10051
|
||||
'''
|
||||
|
||||
RETURN = r''' # '''
|
||||
|
||||
|
||||
import traceback
|
||||
import atexit
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
try:
|
||||
from zabbix_api import ZabbixAPI
|
||||
|
||||
HAS_ZABBIX_API = True
|
||||
except ImportError:
|
||||
ZBX_IMP_ERR = traceback.format_exc()
|
||||
HAS_ZABBIX_API = False
|
||||
|
||||
|
||||
class Proxy(object):
|
||||
def __init__(self, module, zbx):
|
||||
self._module = module
|
||||
self._zapi = zbx
|
||||
self.existing_data = None
|
||||
|
||||
def proxy_exists(self, proxy_name):
|
||||
result = self._zapi.proxy.get({
|
||||
'output': 'extend', 'selectInterface': 'extend',
|
||||
'filter': {'host': proxy_name}})
|
||||
|
||||
if len(result) > 0 and 'proxyid' in result[0]:
|
||||
self.existing_data = result[0]
|
||||
return result[0]['proxyid']
|
||||
else:
|
||||
return result
|
||||
|
||||
def add_proxy(self, data):
|
||||
try:
|
||||
if self._module.check_mode:
|
||||
self._module.exit_json(changed=True)
|
||||
|
||||
parameters = {}
|
||||
for item in data:
|
||||
if data[item]:
|
||||
parameters[item] = data[item]
|
||||
|
||||
if 'proxy_address' in data and data['status'] != '5':
|
||||
parameters.pop('proxy_address', False)
|
||||
|
||||
if 'interface' in data and data['status'] != '6':
|
||||
parameters.pop('interface', False)
|
||||
|
||||
proxy_ids_list = self._zapi.proxy.create(parameters)
|
||||
self._module.exit_json(changed=True,
|
||||
result="Successfully added proxy %s (%s)" %
|
||||
(data['host'], data['status']))
|
||||
if len(proxy_ids_list) >= 1:
|
||||
return proxy_ids_list['proxyids'][0]
|
||||
except Exception as e:
|
||||
self._module.fail_json(msg="Failed to create proxy %s: %s" %
|
||||
(data['host'], e))
|
||||
|
||||
def delete_proxy(self, proxy_id, proxy_name):
|
||||
try:
|
||||
if self._module.check_mode:
|
||||
self._module.exit_json(changed=True)
|
||||
self._zapi.proxy.delete([proxy_id])
|
||||
self._module.exit_json(changed=True,
|
||||
result="Successfully deleted"
|
||||
+ " proxy %s" % proxy_name)
|
||||
except Exception as e:
|
||||
self._module.fail_json(msg="Failed to delete proxy %s: %s" %
|
||||
(proxy_name, str(e)))
|
||||
|
||||
def compile_interface_params(self, new_interface):
|
||||
old_interface = {}
|
||||
if 'interface' in self.existing_data and \
|
||||
len(self.existing_data['interface']) > 0:
|
||||
old_interface = self.existing_data['interface']
|
||||
|
||||
for item in ['type', 'main']:
|
||||
new_interface.pop(item, False)
|
||||
|
||||
final_interface = old_interface.copy()
|
||||
final_interface.update(new_interface)
|
||||
final_interface = dict((k, str(v)) for k, v in final_interface.items())
|
||||
|
||||
if final_interface != old_interface:
|
||||
return final_interface
|
||||
else:
|
||||
return {}
|
||||
|
||||
def update_proxy(self, proxy_id, data):
|
||||
try:
|
||||
if self._module.check_mode:
|
||||
self._module.exit_json(changed=True)
|
||||
parameters = {'proxyid': proxy_id}
|
||||
|
||||
for item in data:
|
||||
if data[item] and item in self.existing_data and \
|
||||
self.existing_data[item] != data[item]:
|
||||
parameters[item] = data[item]
|
||||
|
||||
if 'interface' in parameters:
|
||||
parameters.pop('interface')
|
||||
|
||||
if 'proxy_address' in data and data['status'] != '5':
|
||||
parameters.pop('proxy_address', False)
|
||||
|
||||
if 'interface' in data and data['status'] != '6':
|
||||
parameters.pop('interface', False)
|
||||
|
||||
if 'interface' in data and data['status'] == '6':
|
||||
new_interface = self.compile_interface_params(data['interface'])
|
||||
if len(new_interface) > 0:
|
||||
parameters['interface'] = new_interface
|
||||
|
||||
if len(parameters) > 1:
|
||||
self._zapi.proxy.update(parameters)
|
||||
self._module.exit_json(
|
||||
changed=True,
|
||||
result="Successfully updated proxy %s (%s)" %
|
||||
(data['host'], proxy_id)
|
||||
)
|
||||
else:
|
||||
self._module.exit_json(changed=False)
|
||||
except Exception as e:
|
||||
self._module.fail_json(msg="Failed to update proxy %s: %s" %
|
||||
(data['host'], e))
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
server_url=dict(type='str', required=True, aliases=['url']),
|
||||
login_user=dict(type='str', required=True),
|
||||
login_password=dict(type='str', required=True, no_log=True),
|
||||
proxy_name=dict(type='str', required=True),
|
||||
proxy_address=dict(type='str', required=False),
|
||||
http_login_user=dict(type='str', required=False, default=None),
|
||||
http_login_password=dict(type='str', required=False,
|
||||
default=None, no_log=True),
|
||||
validate_certs=dict(type='bool', required=False, default=True),
|
||||
status=dict(type='str', default="active", choices=['active', 'passive']),
|
||||
state=dict(type='str', default="present", choices=['present', 'absent']),
|
||||
description=dict(type='str', required=False),
|
||||
tls_connect=dict(type='str', default='no_encryption',
|
||||
choices=['no_encryption', 'PSK', 'certificate']),
|
||||
tls_accept=dict(type='str', default='no_encryption',
|
||||
choices=['no_encryption', 'PSK', 'certificate']),
|
||||
ca_cert=dict(type='str', required=False, default=None, aliases=['tls_issuer']),
|
||||
tls_subject=dict(type='str', required=False, default=None),
|
||||
tls_psk_identity=dict(type='str', required=False, default=None),
|
||||
tls_psk=dict(type='str', required=False, default=None),
|
||||
timeout=dict(type='int', default=10),
|
||||
interface=dict(
|
||||
type='dict',
|
||||
required=False,
|
||||
default={},
|
||||
options=dict(
|
||||
useip=dict(type='int', choices=[0, 1], default=0),
|
||||
ip=dict(type='str', default=''),
|
||||
dns=dict(type='str', default=''),
|
||||
port=dict(type='str', default='10051'),
|
||||
type=dict(type='int', default=0, removed_in_version='2.14'),
|
||||
main=dict(type='int', default=0, removed_in_version='2.14')
|
||||
),
|
||||
)
|
||||
),
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
if not HAS_ZABBIX_API:
|
||||
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'), exception=ZBX_IMP_ERR)
|
||||
|
||||
server_url = module.params['server_url']
|
||||
login_user = module.params['login_user']
|
||||
login_password = module.params['login_password']
|
||||
http_login_user = module.params['http_login_user']
|
||||
http_login_password = module.params['http_login_password']
|
||||
validate_certs = module.params['validate_certs']
|
||||
proxy_name = module.params['proxy_name']
|
||||
proxy_address = module.params['proxy_address']
|
||||
description = module.params['description']
|
||||
status = module.params['status']
|
||||
tls_connect = module.params['tls_connect']
|
||||
tls_accept = module.params['tls_accept']
|
||||
tls_issuer = module.params['ca_cert']
|
||||
tls_subject = module.params['tls_subject']
|
||||
tls_psk_identity = module.params['tls_psk_identity']
|
||||
tls_psk = module.params['tls_psk']
|
||||
state = module.params['state']
|
||||
timeout = module.params['timeout']
|
||||
interface = module.params['interface']
|
||||
|
||||
# convert enabled to 0; disabled to 1
|
||||
status = 6 if status == "passive" else 5
|
||||
|
||||
if tls_connect == 'certificate':
|
||||
tls_connect = 4
|
||||
elif tls_connect == 'PSK':
|
||||
tls_connect = 2
|
||||
else:
|
||||
tls_connect = 1
|
||||
|
||||
if tls_accept == 'certificate':
|
||||
tls_accept = 4
|
||||
elif tls_accept == 'PSK':
|
||||
tls_accept = 2
|
||||
else:
|
||||
tls_accept = 1
|
||||
|
||||
zbx = None
|
||||
# login to zabbix
|
||||
try:
|
||||
zbx = ZabbixAPI(server_url, timeout=timeout,
|
||||
user=http_login_user,
|
||||
passwd=http_login_password,
|
||||
validate_certs=validate_certs)
|
||||
zbx.login(login_user, login_password)
|
||||
atexit.register(zbx.logout)
|
||||
except Exception as e:
|
||||
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
|
||||
|
||||
proxy = Proxy(module, zbx)
|
||||
|
||||
# check if proxy already exists
|
||||
proxy_id = proxy.proxy_exists(proxy_name)
|
||||
|
||||
if proxy_id:
|
||||
if state == "absent":
|
||||
# remove proxy
|
||||
proxy.delete_proxy(proxy_id, proxy_name)
|
||||
else:
|
||||
proxy.update_proxy(proxy_id, {
|
||||
'host': proxy_name,
|
||||
'description': description,
|
||||
'status': str(status),
|
||||
'tls_connect': str(tls_connect),
|
||||
'tls_accept': str(tls_accept),
|
||||
'tls_issuer': tls_issuer,
|
||||
'tls_subject': tls_subject,
|
||||
'tls_psk_identity': tls_psk_identity,
|
||||
'tls_psk': tls_psk,
|
||||
'interface': interface,
|
||||
'proxy_address': proxy_address
|
||||
})
|
||||
else:
|
||||
if state == "absent":
|
||||
# the proxy is already deleted.
|
||||
module.exit_json(changed=False)
|
||||
|
||||
proxy_id = proxy.add_proxy(data={
|
||||
'host': proxy_name,
|
||||
'description': description,
|
||||
'status': str(status),
|
||||
'tls_connect': str(tls_connect),
|
||||
'tls_accept': str(tls_accept),
|
||||
'tls_issuer': tls_issuer,
|
||||
'tls_subject': tls_subject,
|
||||
'tls_psk_identity': tls_psk_identity,
|
||||
'tls_psk': tls_psk,
|
||||
'interface': interface,
|
||||
'proxy_address': proxy_address
|
||||
})
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1,471 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# (c) 2013-2014, Epic Games, Inc.
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: zabbix_screen
|
||||
short_description: Create/update/delete Zabbix screens
|
||||
description:
|
||||
- This module allows you to create, modify and delete Zabbix screens and associated graph data.
|
||||
author:
|
||||
- "Cove (@cove)"
|
||||
- "Tony Minfei Ding (!UNKNOWN)"
|
||||
- "Harrison Gu (@harrisongu)"
|
||||
requirements:
|
||||
- "python >= 2.6"
|
||||
- "zabbix-api >= 0.5.4"
|
||||
options:
|
||||
screens:
|
||||
description:
|
||||
- List of screens to be created/updated/deleted (see example).
|
||||
type: list
|
||||
elements: dict
|
||||
required: true
|
||||
suboptions:
|
||||
screen_name:
|
||||
description:
|
||||
- Screen name will be used.
|
||||
- If a screen has already been added, the screen name won't be updated.
|
||||
type: str
|
||||
required: true
|
||||
host_group:
|
||||
description:
|
||||
- Host group will be used for searching hosts.
|
||||
- Required if I(state=present).
|
||||
type: str
|
||||
state:
|
||||
description:
|
||||
- I(present) - Create a screen if it doesn't exist. If the screen already exists, the screen will be updated as needed.
|
||||
- I(absent) - If a screen exists, the screen will be deleted.
|
||||
type: str
|
||||
default: present
|
||||
choices:
|
||||
- absent
|
||||
- present
|
||||
graph_names:
|
||||
description:
|
||||
- Graph names will be added to a screen. Case insensitive.
|
||||
- Required if I(state=present).
|
||||
type: list
|
||||
elements: str
|
||||
graph_width:
|
||||
description:
|
||||
- Graph width will be set in graph settings.
|
||||
type: int
|
||||
graph_height:
|
||||
description:
|
||||
- Graph height will be set in graph settings.
|
||||
type: int
|
||||
graphs_in_row:
|
||||
description:
|
||||
- Limit columns of a screen and make multiple rows.
|
||||
type: int
|
||||
default: 3
|
||||
sort:
|
||||
description:
|
||||
- Sort hosts alphabetically.
|
||||
- If there are numbers in hostnames, leading zero should be used.
|
||||
type: bool
|
||||
default: no
|
||||
|
||||
extends_documentation_fragment:
|
||||
- community.general.zabbix
|
||||
|
||||
|
||||
notes:
|
||||
- Too many concurrent updates to the same screen may cause Zabbix to return errors, see examples for a workaround if needed.
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
# Create/update a screen.
|
||||
- name: Create a new screen or update an existing screen's items 5 in a row
|
||||
local_action:
|
||||
module: zabbix_screen
|
||||
server_url: http://monitor.example.com
|
||||
login_user: username
|
||||
login_password: password
|
||||
screens:
|
||||
- screen_name: ExampleScreen1
|
||||
host_group: Example group1
|
||||
state: present
|
||||
graph_names:
|
||||
- Example graph1
|
||||
- Example graph2
|
||||
graph_width: 200
|
||||
graph_height: 100
|
||||
graphs_in_row: 5
|
||||
|
||||
# Create/update multi-screen
|
||||
- name: Create two of new screens or update the existing screens' items
|
||||
local_action:
|
||||
module: zabbix_screen
|
||||
server_url: http://monitor.example.com
|
||||
login_user: username
|
||||
login_password: password
|
||||
screens:
|
||||
- screen_name: ExampleScreen1
|
||||
host_group: Example group1
|
||||
state: present
|
||||
graph_names:
|
||||
- Example graph1
|
||||
- Example graph2
|
||||
graph_width: 200
|
||||
graph_height: 100
|
||||
- screen_name: ExampleScreen2
|
||||
host_group: Example group2
|
||||
state: present
|
||||
graph_names:
|
||||
- Example graph1
|
||||
- Example graph2
|
||||
graph_width: 200
|
||||
graph_height: 100
|
||||
|
||||
# Limit the Zabbix screen creations to one host since Zabbix can return an error when doing concurrent updates
|
||||
- name: Create a new screen or update an existing screen's items
|
||||
local_action:
|
||||
module: zabbix_screen
|
||||
server_url: http://monitor.example.com
|
||||
login_user: username
|
||||
login_password: password
|
||||
state: present
|
||||
screens:
|
||||
- screen_name: ExampleScreen
|
||||
host_group: Example group
|
||||
state: present
|
||||
graph_names:
|
||||
- Example graph1
|
||||
- Example graph2
|
||||
graph_width: 200
|
||||
graph_height: 100
|
||||
when: inventory_hostname==groups['group_name'][0]
|
||||
'''
|
||||
|
||||
|
||||
import atexit
|
||||
import traceback
|
||||
|
||||
try:
|
||||
from zabbix_api import ZabbixAPI
|
||||
from zabbix_api import ZabbixAPIException
|
||||
from zabbix_api import Already_Exists
|
||||
|
||||
HAS_ZABBIX_API = True
|
||||
except ImportError:
|
||||
ZBX_IMP_ERR = traceback.format_exc()
|
||||
HAS_ZABBIX_API = False
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
|
||||
|
||||
class Screen(object):
|
||||
def __init__(self, module, zbx):
|
||||
self._module = module
|
||||
self._zapi = zbx
|
||||
|
||||
# get group id by group name
|
||||
def get_host_group_id(self, group_name):
|
||||
if group_name == "":
|
||||
self._module.fail_json(msg="group_name is required")
|
||||
hostGroup_list = self._zapi.hostgroup.get({'output': 'extend', 'filter': {'name': group_name}})
|
||||
if len(hostGroup_list) < 1:
|
||||
self._module.fail_json(msg="Host group not found: %s" % group_name)
|
||||
else:
|
||||
hostGroup_id = hostGroup_list[0]['groupid']
|
||||
return hostGroup_id
|
||||
|
||||
# get monitored host_id by host_group_id
|
||||
def get_host_ids_by_group_id(self, group_id, sort):
|
||||
host_list = self._zapi.host.get({'output': 'extend', 'groupids': group_id, 'monitored_hosts': 1})
|
||||
if len(host_list) < 1:
|
||||
self._module.fail_json(msg="No host in the group.")
|
||||
else:
|
||||
if sort:
|
||||
host_list = sorted(host_list, key=lambda name: name['name'])
|
||||
host_ids = []
|
||||
for i in host_list:
|
||||
host_id = i['hostid']
|
||||
host_ids.append(host_id)
|
||||
return host_ids
|
||||
|
||||
# get screen
|
||||
def get_screen_id(self, screen_name):
|
||||
if screen_name == "":
|
||||
self._module.fail_json(msg="screen_name is required")
|
||||
try:
|
||||
screen_id_list = self._zapi.screen.get({'output': 'extend', 'search': {"name": screen_name}})
|
||||
if len(screen_id_list) >= 1:
|
||||
screen_id = screen_id_list[0]['screenid']
|
||||
return screen_id
|
||||
return None
|
||||
except Exception as e:
|
||||
self._module.fail_json(msg="Failed to get screen %s from Zabbix: %s" % (screen_name, e))
|
||||
|
||||
# create screen
|
||||
def create_screen(self, screen_name, h_size, v_size):
|
||||
try:
|
||||
if self._module.check_mode:
|
||||
self._module.exit_json(changed=True)
|
||||
screen = self._zapi.screen.create({'name': screen_name, 'hsize': h_size, 'vsize': v_size})
|
||||
return screen['screenids'][0]
|
||||
except Exception as e:
|
||||
self._module.fail_json(msg="Failed to create screen %s: %s" % (screen_name, e))
|
||||
|
||||
# update screen
|
||||
def update_screen(self, screen_id, screen_name, h_size, v_size):
|
||||
try:
|
||||
if self._module.check_mode:
|
||||
self._module.exit_json(changed=True)
|
||||
self._zapi.screen.update({'screenid': screen_id, 'hsize': h_size, 'vsize': v_size})
|
||||
except Exception as e:
|
||||
self._module.fail_json(msg="Failed to update screen %s: %s" % (screen_name, e))
|
||||
|
||||
# delete screen
|
||||
def delete_screen(self, screen_id, screen_name):
|
||||
try:
|
||||
if self._module.check_mode:
|
||||
self._module.exit_json(changed=True)
|
||||
self._zapi.screen.delete([screen_id])
|
||||
except Exception as e:
|
||||
self._module.fail_json(msg="Failed to delete screen %s: %s" % (screen_name, e))
|
||||
|
||||
# get graph ids
|
||||
def get_graph_ids(self, hosts, graph_name_list):
|
||||
graph_id_lists = []
|
||||
vsize = 1
|
||||
for host in hosts:
|
||||
graph_id_list = self.get_graphs_by_host_id(graph_name_list, host)
|
||||
size = len(graph_id_list)
|
||||
if size > 0:
|
||||
graph_id_lists.extend(graph_id_list)
|
||||
if vsize < size:
|
||||
vsize = size
|
||||
return graph_id_lists, vsize
|
||||
|
||||
# getGraphs
|
||||
def get_graphs_by_host_id(self, graph_name_list, host_id):
|
||||
graph_ids = []
|
||||
for graph_name in graph_name_list:
|
||||
graphs_list = self._zapi.graph.get({'output': 'extend', 'search': {'name': graph_name}, 'hostids': host_id})
|
||||
graph_id_list = []
|
||||
if len(graphs_list) > 0:
|
||||
for graph in graphs_list:
|
||||
graph_id = graph['graphid']
|
||||
graph_id_list.append(graph_id)
|
||||
if len(graph_id_list) > 0:
|
||||
graph_ids.extend(graph_id_list)
|
||||
return graph_ids
|
||||
|
||||
# get screen items
|
||||
def get_screen_items(self, screen_id):
|
||||
screen_item_list = self._zapi.screenitem.get({'output': 'extend', 'screenids': screen_id})
|
||||
return screen_item_list
|
||||
|
||||
# delete screen items
|
||||
def delete_screen_items(self, screen_id, screen_item_id_list):
|
||||
try:
|
||||
if len(screen_item_id_list) == 0:
|
||||
return True
|
||||
screen_item_list = self.get_screen_items(screen_id)
|
||||
if len(screen_item_list) > 0:
|
||||
if self._module.check_mode:
|
||||
self._module.exit_json(changed=True)
|
||||
self._zapi.screenitem.delete(screen_item_id_list)
|
||||
return True
|
||||
return False
|
||||
except ZabbixAPIException:
|
||||
pass
|
||||
|
||||
# get screen's hsize and vsize
|
||||
def get_hsize_vsize(self, hosts, v_size, graphs_in_row):
|
||||
h_size = len(hosts)
|
||||
# when there is only one host, put all graphs in a row
|
||||
if h_size == 1:
|
||||
if v_size <= graphs_in_row:
|
||||
h_size = v_size
|
||||
else:
|
||||
h_size = graphs_in_row
|
||||
v_size = (v_size - 1) // h_size + 1
|
||||
# when len(hosts) is more then graphs_in_row
|
||||
elif len(hosts) > graphs_in_row:
|
||||
h_size = graphs_in_row
|
||||
v_size = (len(hosts) // graphs_in_row + 1) * v_size
|
||||
|
||||
return h_size, v_size
|
||||
|
||||
# create screen_items
|
||||
def create_screen_items(self, screen_id, hosts, graph_name_list, width, height, h_size, graphs_in_row):
|
||||
if len(hosts) < 4:
|
||||
if width is None or width < 0:
|
||||
width = 500
|
||||
else:
|
||||
if width is None or width < 0:
|
||||
width = 200
|
||||
if height is None or height < 0:
|
||||
height = 100
|
||||
|
||||
try:
|
||||
# when there're only one host, only one row is not good.
|
||||
if len(hosts) == 1:
|
||||
graph_id_list = self.get_graphs_by_host_id(graph_name_list, hosts[0])
|
||||
for i, graph_id in enumerate(graph_id_list):
|
||||
if graph_id is not None:
|
||||
self._zapi.screenitem.create({'screenid': screen_id, 'resourcetype': 0, 'resourceid': graph_id,
|
||||
'width': width, 'height': height,
|
||||
'x': i % h_size, 'y': i // h_size, 'colspan': 1, 'rowspan': 1,
|
||||
'elements': 0, 'valign': 0, 'halign': 0,
|
||||
'style': 0, 'dynamic': 0, 'sort_triggers': 0})
|
||||
else:
|
||||
for i, host in enumerate(hosts):
|
||||
graph_id_list = self.get_graphs_by_host_id(graph_name_list, host)
|
||||
for j, graph_id in enumerate(graph_id_list):
|
||||
if graph_id is not None:
|
||||
self._zapi.screenitem.create({'screenid': screen_id, 'resourcetype': 0, 'resourceid': graph_id,
|
||||
'width': width, 'height': height,
|
||||
'x': i % graphs_in_row, 'y': len(graph_id_list) * (i // graphs_in_row) + j,
|
||||
'colspan': 1, 'rowspan': 1,
|
||||
'elements': 0, 'valign': 0, 'halign': 0,
|
||||
'style': 0, 'dynamic': 0, 'sort_triggers': 0})
|
||||
except Already_Exists:
|
||||
pass
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
server_url=dict(type='str', required=True, aliases=['url']),
|
||||
login_user=dict(type='str', required=True),
|
||||
login_password=dict(type='str', required=True, no_log=True),
|
||||
http_login_user=dict(type='str', required=False, default=None),
|
||||
http_login_password=dict(type='str', required=False, default=None, no_log=True),
|
||||
validate_certs=dict(type='bool', required=False, default=True),
|
||||
timeout=dict(type='int', default=10),
|
||||
screens=dict(
|
||||
type='list',
|
||||
elements='dict',
|
||||
required=True,
|
||||
options=dict(
|
||||
screen_name=dict(type='str', required=True),
|
||||
host_group=dict(type='str'),
|
||||
state=dict(type='str', default='present', choices=['absent', 'present']),
|
||||
graph_names=dict(type='list', elements='str'),
|
||||
graph_width=dict(type='int', default=None),
|
||||
graph_height=dict(type='int', default=None),
|
||||
graphs_in_row=dict(type='int', default=3),
|
||||
sort=dict(default=False, type='bool'),
|
||||
),
|
||||
required_if=[
|
||||
['state', 'present', ['host_group']]
|
||||
]
|
||||
)
|
||||
),
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
if not HAS_ZABBIX_API:
|
||||
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'), exception=ZBX_IMP_ERR)
|
||||
|
||||
server_url = module.params['server_url']
|
||||
login_user = module.params['login_user']
|
||||
login_password = module.params['login_password']
|
||||
http_login_user = module.params['http_login_user']
|
||||
http_login_password = module.params['http_login_password']
|
||||
validate_certs = module.params['validate_certs']
|
||||
timeout = module.params['timeout']
|
||||
screens = module.params['screens']
|
||||
|
||||
zbx = None
|
||||
# login to zabbix
|
||||
try:
|
||||
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
|
||||
validate_certs=validate_certs)
|
||||
zbx.login(login_user, login_password)
|
||||
atexit.register(zbx.logout)
|
||||
except Exception as e:
|
||||
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
|
||||
|
||||
screen = Screen(module, zbx)
|
||||
created_screens = []
|
||||
changed_screens = []
|
||||
deleted_screens = []
|
||||
|
||||
for zabbix_screen in screens:
|
||||
screen_name = zabbix_screen['screen_name']
|
||||
screen_id = screen.get_screen_id(screen_name)
|
||||
state = zabbix_screen['state']
|
||||
sort = zabbix_screen['sort']
|
||||
|
||||
if state == "absent":
|
||||
if screen_id:
|
||||
screen_item_list = screen.get_screen_items(screen_id)
|
||||
screen_item_id_list = []
|
||||
for screen_item in screen_item_list:
|
||||
screen_item_id = screen_item['screenitemid']
|
||||
screen_item_id_list.append(screen_item_id)
|
||||
screen.delete_screen_items(screen_id, screen_item_id_list)
|
||||
screen.delete_screen(screen_id, screen_name)
|
||||
|
||||
deleted_screens.append(screen_name)
|
||||
else:
|
||||
host_group = zabbix_screen['host_group']
|
||||
graph_names = zabbix_screen['graph_names']
|
||||
graphs_in_row = zabbix_screen['graphs_in_row']
|
||||
graph_width = zabbix_screen['graph_width']
|
||||
graph_height = zabbix_screen['graph_height']
|
||||
host_group_id = screen.get_host_group_id(host_group)
|
||||
hosts = screen.get_host_ids_by_group_id(host_group_id, sort)
|
||||
|
||||
screen_item_id_list = []
|
||||
resource_id_list = []
|
||||
|
||||
graph_ids, v_size = screen.get_graph_ids(hosts, graph_names)
|
||||
h_size, v_size = screen.get_hsize_vsize(hosts, v_size, graphs_in_row)
|
||||
|
||||
if not screen_id:
|
||||
# create screen
|
||||
screen_id = screen.create_screen(screen_name, h_size, v_size)
|
||||
screen.create_screen_items(screen_id, hosts, graph_names, graph_width, graph_height, h_size, graphs_in_row)
|
||||
created_screens.append(screen_name)
|
||||
else:
|
||||
screen_item_list = screen.get_screen_items(screen_id)
|
||||
|
||||
for screen_item in screen_item_list:
|
||||
screen_item_id = screen_item['screenitemid']
|
||||
resource_id = screen_item['resourceid']
|
||||
screen_item_id_list.append(screen_item_id)
|
||||
resource_id_list.append(resource_id)
|
||||
|
||||
# when the screen items changed, then update
|
||||
if graph_ids != resource_id_list:
|
||||
deleted = screen.delete_screen_items(screen_id, screen_item_id_list)
|
||||
if deleted:
|
||||
screen.update_screen(screen_id, screen_name, h_size, v_size)
|
||||
screen.create_screen_items(screen_id, hosts, graph_names, graph_width, graph_height, h_size, graphs_in_row)
|
||||
changed_screens.append(screen_name)
|
||||
|
||||
if created_screens and changed_screens:
|
||||
module.exit_json(changed=True, result="Successfully created screen(s): %s, and updated screen(s): %s" % (",".join(created_screens),
|
||||
",".join(changed_screens)))
|
||||
elif created_screens:
|
||||
module.exit_json(changed=True, result="Successfully created screen(s): %s" % ",".join(created_screens))
|
||||
elif changed_screens:
|
||||
module.exit_json(changed=True, result="Successfully updated screen(s): %s" % ",".join(changed_screens))
|
||||
elif deleted_screens:
|
||||
module.exit_json(changed=True, result="Successfully deleted screen(s): %s" % ",".join(deleted_screens))
|
||||
else:
|
||||
module.exit_json(changed=False)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1,291 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# (c) 2019, OVH SAS
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: zabbix_service
|
||||
short_description: Create/update/delete Zabbix service
|
||||
description:
|
||||
- Create/update/delete Zabbix service.
|
||||
author:
|
||||
- "Emmanuel Riviere (@emriver)"
|
||||
requirements:
|
||||
- "python >= 2.7"
|
||||
- "zabbix-api >= 0.5.4"
|
||||
options:
|
||||
name:
|
||||
description:
|
||||
- Name of Zabbix service
|
||||
required: true
|
||||
type: str
|
||||
parent:
|
||||
description:
|
||||
- Name of Zabbix service parent
|
||||
required: false
|
||||
type: str
|
||||
sla:
|
||||
description:
|
||||
- Sla value (i.e 99.99), goodsla in Zabbix API
|
||||
required: false
|
||||
type: float
|
||||
calculate_sla:
|
||||
description:
|
||||
- If yes, calculate the SLA value for this service, showsla in Zabbix API
|
||||
required: false
|
||||
type: bool
|
||||
algorithm:
|
||||
description:
|
||||
- Algorithm used to calculate the sla
|
||||
- C(no), sla is not calculated
|
||||
- C(one_child), problem if at least one child has a problem
|
||||
- C(all_children), problem if all children have problems
|
||||
required: false
|
||||
type: str
|
||||
choices: ["no", "one_child", "all_children"]
|
||||
default: one_child
|
||||
trigger_name:
|
||||
description:
|
||||
- Name of trigger linked to the service
|
||||
required: false
|
||||
type: str
|
||||
trigger_host:
|
||||
description:
|
||||
- Name of host linked to the service
|
||||
required: false
|
||||
type: str
|
||||
state:
|
||||
description:
|
||||
- 'State: present - create/update service; absent - delete service'
|
||||
required: false
|
||||
choices: [present, absent]
|
||||
default: "present"
|
||||
type: str
|
||||
|
||||
extends_documentation_fragment:
|
||||
- community.general.zabbix
|
||||
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
---
|
||||
# Creates a new Zabbix service
|
||||
- name: Manage services
|
||||
local_action:
|
||||
module: zabbix_service
|
||||
server_url: "https://192.168.1.1"
|
||||
login_user: username
|
||||
login_password: password
|
||||
name: apache2 service
|
||||
sla: 99.99
|
||||
calculate_sla: yes
|
||||
algorithm: one_child
|
||||
trigger_name: apache2 service status
|
||||
trigger_host: webserver01
|
||||
state: present
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
---
|
||||
'''
|
||||
|
||||
import atexit
|
||||
import traceback
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
|
||||
|
||||
try:
|
||||
from zabbix_api import ZabbixAPI, ZabbixAPIException
|
||||
HAS_ZABBIX_API = True
|
||||
except ImportError:
|
||||
ZBX_IMP_ERR = traceback.format_exc()
|
||||
HAS_ZABBIX_API = False
|
||||
|
||||
|
||||
class Service(object):
|
||||
def __init__(self, module, zbx):
|
||||
self._module = module
|
||||
self._zapi = zbx
|
||||
|
||||
def get_service_ids(self, service_name):
|
||||
service_ids = []
|
||||
services = self._zapi.service.get({'filter': {'name': service_name}})
|
||||
for service in services:
|
||||
service_ids.append(service['serviceid'])
|
||||
return service_ids
|
||||
|
||||
def delete_service(self, service_ids):
|
||||
if self._module.check_mode:
|
||||
self._module.exit_json(changed=True)
|
||||
self._zapi.service.delete(service_ids)
|
||||
|
||||
def dump_services(self, service_ids):
|
||||
services = self._zapi.service.get({'output': 'extend', 'filter': {'serviceid': service_ids}, 'selectParent': '1'})
|
||||
return services
|
||||
|
||||
def generate_service_config(self, name, parent, sla, calculate_sla, trigger_name, trigger_host, algorithm):
|
||||
algorithms = {'no': '0', 'one_child': '1', 'all_children': '2'}
|
||||
algorithm = algorithms[algorithm]
|
||||
|
||||
if calculate_sla:
|
||||
calculate_sla = 1
|
||||
else:
|
||||
calculate_sla = 0
|
||||
|
||||
# Zabbix api return when no trigger
|
||||
trigger_id = 0
|
||||
if trigger_host and trigger_name:
|
||||
# Retrieving the host to get the trigger
|
||||
hosts = self._zapi.host.get({'filter': {'host': trigger_host}})
|
||||
if not hosts:
|
||||
self._module.fail_json(msg="Target host %s not found" % trigger_host)
|
||||
host_id = hosts[0]['hostid']
|
||||
|
||||
triggers = self._zapi.trigger.get({'filter': {'description': trigger_name}, 'hostids': [host_id]})
|
||||
if not triggers:
|
||||
self._module.fail_json(msg="Trigger %s not found on host %s" % (trigger_name, trigger_host))
|
||||
trigger_id = triggers[0]['triggerid']
|
||||
|
||||
request = {
|
||||
'name': name,
|
||||
'algorithm': algorithm,
|
||||
'showsla': calculate_sla,
|
||||
'sortorder': 1,
|
||||
'goodsla': format(sla, '.4f'), # Sla has 4 decimals
|
||||
'triggerid': trigger_id
|
||||
}
|
||||
|
||||
if parent:
|
||||
parent_ids = self.get_service_ids(parent)
|
||||
if not parent_ids:
|
||||
self._module.fail_json(msg="Parent %s not found" % parent)
|
||||
request['parentid'] = parent_ids[0]
|
||||
return request
|
||||
|
||||
def create_service(self, name, parent, sla, calculate_sla, trigger_name, trigger_host, algorithm):
|
||||
if self._module.check_mode:
|
||||
self._module.exit_json(changed=True)
|
||||
self._zapi.service.create(self.generate_service_config(name, parent, sla, calculate_sla, trigger_name, trigger_host, algorithm))
|
||||
|
||||
def update_service(self, service_id, name, parent, sla, calculate_sla, trigger_name, trigger_host, algorithm):
|
||||
generated_config = self.generate_service_config(name, parent, sla, calculate_sla, trigger_name, trigger_host, algorithm)
|
||||
live_config = self.dump_services(service_id)[0]
|
||||
|
||||
item_to_check = ['name', 'showsla', 'algorithm', 'triggerid', 'sortorder', 'goodsla']
|
||||
change = False
|
||||
for item in item_to_check:
|
||||
if str(generated_config[item]) != str(live_config[item]):
|
||||
change = True
|
||||
|
||||
# In Zabbix 4.0
|
||||
# No parent returns : "parent": []
|
||||
# A parent returns : "parent": { "serviceid": 12 }
|
||||
if 'parentid' in generated_config:
|
||||
if 'serviceid' in live_config['parent']:
|
||||
if generated_config['parentid'] != live_config['parent']['serviceid']:
|
||||
change = True
|
||||
else:
|
||||
change = True
|
||||
elif 'serviceid' in live_config['parent']:
|
||||
change = True
|
||||
|
||||
if not change:
|
||||
self._module.exit_json(changed=False, msg="Service %s up to date" % name)
|
||||
|
||||
if self._module.check_mode:
|
||||
self._module.exit_json(changed=True)
|
||||
generated_config['serviceid'] = service_id
|
||||
self._zapi.service.update(generated_config)
|
||||
self._module.exit_json(changed=True, msg="Service %s updated" % name)
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
server_url=dict(type='str', required=True, aliases=['url']),
|
||||
login_user=dict(type='str', required=True),
|
||||
login_password=dict(type='str', required=True, no_log=True),
|
||||
http_login_user=dict(type='str', required=False, default=None),
|
||||
http_login_password=dict(type='str', required=False, default=None, no_log=True),
|
||||
validate_certs=dict(type='bool', required=False, default=True),
|
||||
name=dict(type='str', required=True),
|
||||
parent=dict(type='str', required=False),
|
||||
sla=dict(type='float', required=False),
|
||||
calculate_sla=dict(type='bool', required=False, default=False),
|
||||
algorithm=dict(default='one_child', required=False, choices=['no', 'one_child', 'all_children']),
|
||||
trigger_name=dict(type='str', required=False),
|
||||
trigger_host=dict(type='str', required=False),
|
||||
state=dict(default="present", choices=['present', 'absent']),
|
||||
timeout=dict(type='int', default=10)
|
||||
),
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
if not HAS_ZABBIX_API:
|
||||
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'), exception=ZBX_IMP_ERR)
|
||||
|
||||
server_url = module.params['server_url']
|
||||
login_user = module.params['login_user']
|
||||
login_password = module.params['login_password']
|
||||
http_login_user = module.params['http_login_user']
|
||||
http_login_password = module.params['http_login_password']
|
||||
validate_certs = module.params['validate_certs']
|
||||
name = module.params['name']
|
||||
parent = module.params['parent']
|
||||
sla = module.params['sla']
|
||||
calculate_sla = module.params['calculate_sla']
|
||||
algorithm = module.params['algorithm']
|
||||
trigger_name = module.params['trigger_name']
|
||||
trigger_host = module.params['trigger_host']
|
||||
state = module.params['state']
|
||||
timeout = module.params['timeout']
|
||||
|
||||
zbx = None
|
||||
|
||||
# Login to zabbix
|
||||
try:
|
||||
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password, validate_certs=validate_certs)
|
||||
zbx.login(login_user, login_password)
|
||||
atexit.register(zbx.logout)
|
||||
except ZabbixAPIException as error:
|
||||
module.fail_json(msg="Failed to connect to Zabbix server: %s" % error)
|
||||
|
||||
# Load service module
|
||||
service = Service(module, zbx)
|
||||
service_ids = service.get_service_ids(name)
|
||||
if service_ids:
|
||||
service_json = service.dump_services(service_ids)
|
||||
|
||||
# Delete service
|
||||
if state == "absent":
|
||||
if not service_ids:
|
||||
module.exit_json(changed=False, msg="Service not found, no change: %s" % name)
|
||||
service.delete_service(service_ids)
|
||||
module.exit_json(changed=True, result="Successfully deleted service(s) %s" % name)
|
||||
|
||||
elif state == "present":
|
||||
if (trigger_name and not trigger_host) or (trigger_host and not trigger_name):
|
||||
module.fail_json(msg="Specify either both trigger_host and trigger_name or none to create or update a service")
|
||||
# Does not exists going to create it
|
||||
if not service_ids:
|
||||
service.create_service(name, parent, sla, calculate_sla, trigger_name, trigger_host, algorithm)
|
||||
module.exit_json(changed=True, msg="Service %s created" % name)
|
||||
# Else we update it if needed
|
||||
else:
|
||||
service.update_service(service_ids[0], name, parent, sla, calculate_sla, trigger_name, trigger_host, algorithm)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1,795 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# (c) 2017, sookido
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: zabbix_template
|
||||
short_description: Create/update/delete/dump Zabbix template
|
||||
description:
|
||||
- This module allows you to create, modify, delete and dump Zabbix templates.
|
||||
- Multiple templates can be created or modified at once if passing JSON or XML to module.
|
||||
author:
|
||||
- "sookido (@sookido)"
|
||||
- "Logan Vig (@logan2211)"
|
||||
- "Dusan Matejka (@D3DeFi)"
|
||||
requirements:
|
||||
- "python >= 2.6"
|
||||
- "zabbix-api >= 0.5.4"
|
||||
options:
|
||||
template_name:
|
||||
description:
|
||||
- Name of Zabbix template.
|
||||
- Required when I(template_json) or I(template_xml) are not used.
|
||||
- Mutually exclusive with I(template_json) and I(template_xml).
|
||||
required: false
|
||||
type: str
|
||||
template_json:
|
||||
description:
|
||||
- JSON dump of templates to import.
|
||||
- Multiple templates can be imported this way.
|
||||
- Mutually exclusive with I(template_name) and I(template_xml).
|
||||
required: false
|
||||
type: json
|
||||
template_xml:
|
||||
description:
|
||||
- XML dump of templates to import.
|
||||
- Multiple templates can be imported this way.
|
||||
- You are advised to pass XML structure matching the structure used by your version of Zabbix server.
|
||||
- Custom XML structure can be imported as long as it is valid, but may not yield consistent idempotent
|
||||
results on subsequent runs.
|
||||
- Mutually exclusive with I(template_name) and I(template_json).
|
||||
required: false
|
||||
type: str
|
||||
template_groups:
|
||||
description:
|
||||
- List of host groups to add template to when template is created.
|
||||
- Replaces the current host groups the template belongs to if the template is already present.
|
||||
- Required when creating a new template with C(state=present) and I(template_name) is used.
|
||||
Not required when updating an existing template.
|
||||
required: false
|
||||
type: list
|
||||
elements: str
|
||||
link_templates:
|
||||
description:
|
||||
- List of template names to be linked to the template.
|
||||
- Templates that are not specified and are linked to the existing template will be only unlinked and not
|
||||
cleared from the template.
|
||||
required: false
|
||||
type: list
|
||||
elements: str
|
||||
clear_templates:
|
||||
description:
|
||||
- List of template names to be unlinked and cleared from the template.
|
||||
- This option is ignored if template is being created for the first time.
|
||||
required: false
|
||||
type: list
|
||||
elements: str
|
||||
macros:
|
||||
description:
|
||||
- List of user macros to create for the template.
|
||||
- Macros that are not specified and are present on the existing template will be replaced.
|
||||
- See examples on how to pass macros.
|
||||
required: false
|
||||
type: list
|
||||
elements: dict
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Name of the macro.
|
||||
- Must be specified in {$NAME} format.
|
||||
type: str
|
||||
value:
|
||||
description:
|
||||
- Value of the macro.
|
||||
type: str
|
||||
dump_format:
|
||||
description:
|
||||
- Format to use when dumping template with C(state=dump).
|
||||
- This option is deprecated and will eventually be removed in 2.14.
|
||||
required: false
|
||||
choices: [json, xml]
|
||||
default: "json"
|
||||
type: str
|
||||
omit_date:
|
||||
description:
|
||||
- Removes the date field for the exported/dumped template
|
||||
- Requires C(state=dump)
|
||||
required: false
|
||||
type: bool
|
||||
default: false
|
||||
state:
|
||||
description:
|
||||
- Required state of the template.
|
||||
- On C(state=present) template will be created/imported or updated depending if it is already present.
|
||||
- On C(state=dump) template content will get dumped into required format specified in I(dump_format).
|
||||
- On C(state=absent) template will be deleted.
|
||||
- The C(state=dump) is deprecated and will eventually be removed in 2.14. The M(zabbix_template_info) module should be used instead.
|
||||
required: false
|
||||
choices: [present, absent, dump]
|
||||
default: "present"
|
||||
type: str
|
||||
|
||||
extends_documentation_fragment:
|
||||
- community.general.zabbix
|
||||
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
---
|
||||
- name: Create a new Zabbix template linked to groups, macros and templates
|
||||
local_action:
|
||||
module: zabbix_template
|
||||
server_url: http://127.0.0.1
|
||||
login_user: username
|
||||
login_password: password
|
||||
template_name: ExampleHost
|
||||
template_groups:
|
||||
- Role
|
||||
- Role2
|
||||
link_templates:
|
||||
- Example template1
|
||||
- Example template2
|
||||
macros:
|
||||
- macro: '{$EXAMPLE_MACRO1}'
|
||||
value: 30000
|
||||
- macro: '{$EXAMPLE_MACRO2}'
|
||||
value: 3
|
||||
- macro: '{$EXAMPLE_MACRO3}'
|
||||
value: 'Example'
|
||||
state: present
|
||||
|
||||
- name: Unlink and clear templates from the existing Zabbix template
|
||||
local_action:
|
||||
module: zabbix_template
|
||||
server_url: http://127.0.0.1
|
||||
login_user: username
|
||||
login_password: password
|
||||
template_name: ExampleHost
|
||||
clear_templates:
|
||||
- Example template3
|
||||
- Example template4
|
||||
state: present
|
||||
|
||||
- name: Import Zabbix templates from JSON
|
||||
local_action:
|
||||
module: zabbix_template
|
||||
server_url: http://127.0.0.1
|
||||
login_user: username
|
||||
login_password: password
|
||||
template_json: "{{ lookup('file', 'zabbix_apache2.json') }}"
|
||||
state: present
|
||||
|
||||
- name: Import Zabbix templates from XML
|
||||
local_action:
|
||||
module: zabbix_template
|
||||
server_url: http://127.0.0.1
|
||||
login_user: username
|
||||
login_password: password
|
||||
template_xml: "{{ lookup('file', 'zabbix_apache2.json') }}"
|
||||
state: present
|
||||
|
||||
- name: Import Zabbix template from Ansible dict variable
|
||||
zabbix_template:
|
||||
login_user: username
|
||||
login_password: password
|
||||
server_url: http://127.0.0.1
|
||||
template_json:
|
||||
zabbix_export:
|
||||
version: '3.2'
|
||||
templates:
|
||||
- name: Template for Testing
|
||||
description: 'Testing template import'
|
||||
template: Test Template
|
||||
groups:
|
||||
- name: Templates
|
||||
applications:
|
||||
- name: Test Application
|
||||
state: present
|
||||
|
||||
- name: Configure macros on the existing Zabbix template
|
||||
local_action:
|
||||
module: zabbix_template
|
||||
server_url: http://127.0.0.1
|
||||
login_user: username
|
||||
login_password: password
|
||||
template_name: Template
|
||||
macros:
|
||||
- macro: '{$TEST_MACRO}'
|
||||
value: 'Example'
|
||||
state: present
|
||||
|
||||
- name: Delete Zabbix template
|
||||
local_action:
|
||||
module: zabbix_template
|
||||
server_url: http://127.0.0.1
|
||||
login_user: username
|
||||
login_password: password
|
||||
template_name: Template
|
||||
state: absent
|
||||
|
||||
- name: Dump Zabbix template as JSON
|
||||
local_action:
|
||||
module: zabbix_template
|
||||
server_url: http://127.0.0.1
|
||||
login_user: username
|
||||
login_password: password
|
||||
template_name: Template
|
||||
omit_date: yes
|
||||
state: dump
|
||||
register: template_dump
|
||||
|
||||
- name: Dump Zabbix template as XML
|
||||
local_action:
|
||||
module: zabbix_template
|
||||
server_url: http://127.0.0.1
|
||||
login_user: username
|
||||
login_password: password
|
||||
template_name: Template
|
||||
dump_format: xml
|
||||
omit_date: false
|
||||
state: dump
|
||||
register: template_dump
|
||||
'''
|
||||
|
||||
RETURN = r'''
|
||||
---
|
||||
template_json:
|
||||
description: The JSON dump of the template
|
||||
returned: when state is dump and omit_date is no
|
||||
type: str
|
||||
sample: {
|
||||
"zabbix_export":{
|
||||
"date":"2017-11-29T16:37:24Z",
|
||||
"templates":[{
|
||||
"templates":[],
|
||||
"description":"",
|
||||
"httptests":[],
|
||||
"screens":[],
|
||||
"applications":[],
|
||||
"discovery_rules":[],
|
||||
"groups":[{"name":"Templates"}],
|
||||
"name":"Test Template",
|
||||
"items":[],
|
||||
"macros":[],
|
||||
"template":"test"
|
||||
}],
|
||||
"version":"3.2",
|
||||
"groups":[{
|
||||
"name":"Templates"
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
template_xml:
|
||||
description: dump of the template in XML representation
|
||||
returned: when state is dump, dump_format is xml and omit_date is yes
|
||||
type: str
|
||||
sample: |-
|
||||
<?xml version="1.0" ?>
|
||||
<zabbix_export>
|
||||
<version>4.2</version>
|
||||
<groups>
|
||||
<group>
|
||||
<name>Templates</name>
|
||||
</group>
|
||||
</groups>
|
||||
<templates>
|
||||
<template>
|
||||
<template>test</template>
|
||||
<name>Test Template</name>
|
||||
<description/>
|
||||
<groups>
|
||||
<group>
|
||||
<name>Templates</name>
|
||||
</group>
|
||||
</groups>
|
||||
<applications/>
|
||||
<items/>
|
||||
<discovery_rules/>
|
||||
<httptests/>
|
||||
<macros/>
|
||||
<templates/>
|
||||
<screens/>
|
||||
<tags/>
|
||||
</template>
|
||||
</templates>
|
||||
</zabbix_export>
|
||||
'''
|
||||
|
||||
|
||||
import atexit
|
||||
import json
|
||||
import traceback
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
from distutils.version import LooseVersion
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
from ansible.module_utils._text import to_native
|
||||
|
||||
try:
|
||||
from zabbix_api import ZabbixAPI, ZabbixAPIException
|
||||
|
||||
HAS_ZABBIX_API = True
|
||||
except ImportError:
|
||||
ZBX_IMP_ERR = traceback.format_exc()
|
||||
HAS_ZABBIX_API = False
|
||||
|
||||
|
||||
class Template(object):
|
||||
def __init__(self, module, zbx):
|
||||
self._module = module
|
||||
self._zapi = zbx
|
||||
|
||||
# check if host group exists
|
||||
def check_host_group_exist(self, group_names):
|
||||
for group_name in group_names:
|
||||
result = self._zapi.hostgroup.get({'filter': {'name': group_name}})
|
||||
if not result:
|
||||
self._module.fail_json(msg="Hostgroup not found: %s" %
|
||||
group_name)
|
||||
return True
|
||||
|
||||
# get group ids by group names
|
||||
def get_group_ids_by_group_names(self, group_names):
|
||||
group_ids = []
|
||||
if group_names is None or len(group_names) == 0:
|
||||
return group_ids
|
||||
if self.check_host_group_exist(group_names):
|
||||
group_list = self._zapi.hostgroup.get(
|
||||
{'output': 'extend',
|
||||
'filter': {'name': group_names}})
|
||||
for group in group_list:
|
||||
group_id = group['groupid']
|
||||
group_ids.append({'groupid': group_id})
|
||||
return group_ids
|
||||
|
||||
def get_template_ids(self, template_list):
|
||||
template_ids = []
|
||||
if template_list is None or len(template_list) == 0:
|
||||
return template_ids
|
||||
for template in template_list:
|
||||
template_list = self._zapi.template.get(
|
||||
{'output': 'extend',
|
||||
'filter': {'host': template}})
|
||||
if len(template_list) < 1:
|
||||
continue
|
||||
else:
|
||||
template_id = template_list[0]['templateid']
|
||||
template_ids.append(template_id)
|
||||
return template_ids
|
||||
|
||||
def add_template(self, template_name, group_ids, link_template_ids, macros):
|
||||
if self._module.check_mode:
|
||||
self._module.exit_json(changed=True)
|
||||
|
||||
self._zapi.template.create({'host': template_name, 'groups': group_ids, 'templates': link_template_ids,
|
||||
'macros': macros})
|
||||
|
||||
def check_template_changed(self, template_ids, template_groups, link_templates, clear_templates,
|
||||
template_macros, template_content, template_type):
|
||||
"""Compares template parameters to already existing values if any are found.
|
||||
|
||||
template_json - JSON structures are compared as deep sorted dictionaries,
|
||||
template_xml - XML structures are compared as strings, but filtered and formatted first,
|
||||
If none above is used, all the other arguments are compared to their existing counterparts
|
||||
retrieved from Zabbix API."""
|
||||
changed = False
|
||||
# Compare filtered and formatted XMLs strings for any changes. It is expected that provided
|
||||
# XML has same structure as Zabbix uses (e.g. it was optimally exported via Zabbix GUI or API)
|
||||
if template_content is not None and template_type == 'xml':
|
||||
existing_template = self.dump_template(template_ids, template_type='xml')
|
||||
|
||||
if self.filter_xml_template(template_content) != self.filter_xml_template(existing_template):
|
||||
changed = True
|
||||
|
||||
return changed
|
||||
|
||||
existing_template = self.dump_template(template_ids, template_type='json')
|
||||
# Compare JSON objects as deep sorted python dictionaries
|
||||
if template_content is not None and template_type == 'json':
|
||||
parsed_template_json = self.load_json_template(template_content)
|
||||
if self.diff_template(parsed_template_json, existing_template):
|
||||
changed = True
|
||||
|
||||
return changed
|
||||
|
||||
# If neither template_json or template_xml were used, user provided all parameters via module options
|
||||
if template_groups is not None:
|
||||
existing_groups = [g['name'] for g in existing_template['zabbix_export']['groups']]
|
||||
|
||||
if set(template_groups) != set(existing_groups):
|
||||
changed = True
|
||||
|
||||
if 'templates' not in existing_template['zabbix_export']['templates'][0]:
|
||||
existing_template['zabbix_export']['templates'][0]['templates'] = []
|
||||
|
||||
# Check if any new templates would be linked or any existing would be unlinked
|
||||
exist_child_templates = [t['name'] for t in existing_template['zabbix_export']['templates'][0]['templates']]
|
||||
if link_templates is not None:
|
||||
if set(link_templates) != set(exist_child_templates):
|
||||
changed = True
|
||||
else:
|
||||
if set([]) != set(exist_child_templates):
|
||||
changed = True
|
||||
|
||||
# Mark that there will be changes when at least one existing template will be unlinked
|
||||
if clear_templates is not None:
|
||||
for t in clear_templates:
|
||||
if t in exist_child_templates:
|
||||
changed = True
|
||||
break
|
||||
|
||||
if 'macros' not in existing_template['zabbix_export']['templates'][0]:
|
||||
existing_template['zabbix_export']['templates'][0]['macros'] = []
|
||||
|
||||
if template_macros is not None:
|
||||
existing_macros = existing_template['zabbix_export']['templates'][0]['macros']
|
||||
if template_macros != existing_macros:
|
||||
changed = True
|
||||
|
||||
return changed
|
||||
|
||||
def update_template(self, template_ids, group_ids, link_template_ids, clear_template_ids, template_macros):
|
||||
template_changes = {}
|
||||
if group_ids is not None:
|
||||
template_changes.update({'groups': group_ids})
|
||||
|
||||
if link_template_ids is not None:
|
||||
template_changes.update({'templates': link_template_ids})
|
||||
else:
|
||||
template_changes.update({'templates': []})
|
||||
|
||||
if clear_template_ids is not None:
|
||||
template_changes.update({'templates_clear': clear_template_ids})
|
||||
|
||||
if template_macros is not None:
|
||||
template_changes.update({'macros': template_macros})
|
||||
|
||||
if template_changes:
|
||||
# If we got here we know that only one template was provided via template_name
|
||||
template_changes.update({'templateid': template_ids[0]})
|
||||
self._zapi.template.update(template_changes)
|
||||
|
||||
def delete_template(self, templateids):
|
||||
if self._module.check_mode:
|
||||
self._module.exit_json(changed=True)
|
||||
self._zapi.template.delete(templateids)
|
||||
|
||||
def ordered_json(self, obj):
|
||||
# Deep sort json dicts for comparison
|
||||
if isinstance(obj, dict):
|
||||
return sorted((k, self.ordered_json(v)) for k, v in obj.items())
|
||||
if isinstance(obj, list):
|
||||
return sorted(self.ordered_json(x) for x in obj)
|
||||
else:
|
||||
return obj
|
||||
|
||||
def dump_template(self, template_ids, template_type='json', omit_date=False):
|
||||
if self._module.check_mode:
|
||||
self._module.exit_json(changed=True)
|
||||
|
||||
try:
|
||||
dump = self._zapi.configuration.export({'format': template_type, 'options': {'templates': template_ids}})
|
||||
if template_type == 'xml':
|
||||
xmlroot = ET.fromstring(dump.encode('utf-8'))
|
||||
# remove date field if requested
|
||||
if omit_date:
|
||||
date = xmlroot.find(".date")
|
||||
if date is not None:
|
||||
xmlroot.remove(date)
|
||||
return str(ET.tostring(xmlroot, encoding='utf-8').decode('utf-8'))
|
||||
else:
|
||||
return self.load_json_template(dump, omit_date=omit_date)
|
||||
|
||||
except ZabbixAPIException as e:
|
||||
self._module.fail_json(msg='Unable to export template: %s' % e)
|
||||
|
||||
def diff_template(self, template_json_a, template_json_b):
|
||||
# Compare 2 zabbix templates and return True if they differ.
|
||||
template_json_a = self.filter_template(template_json_a)
|
||||
template_json_b = self.filter_template(template_json_b)
|
||||
if self.ordered_json(template_json_a) == self.ordered_json(template_json_b):
|
||||
return False
|
||||
return True
|
||||
|
||||
def filter_template(self, template_json):
|
||||
# Filter the template json to contain only the keys we will update
|
||||
keep_keys = set(['graphs', 'templates', 'triggers', 'value_maps'])
|
||||
unwanted_keys = set(template_json['zabbix_export']) - keep_keys
|
||||
for unwanted_key in unwanted_keys:
|
||||
del template_json['zabbix_export'][unwanted_key]
|
||||
|
||||
# Versions older than 2.4 do not support description field within template
|
||||
desc_not_supported = False
|
||||
if LooseVersion(self._zapi.api_version()).version[:2] < LooseVersion('2.4').version:
|
||||
desc_not_supported = True
|
||||
|
||||
# Filter empty attributes from template object to allow accurate comparison
|
||||
for template in template_json['zabbix_export']['templates']:
|
||||
for key in list(template.keys()):
|
||||
if not template[key] or (key == 'description' and desc_not_supported):
|
||||
template.pop(key)
|
||||
|
||||
return template_json
|
||||
|
||||
def filter_xml_template(self, template_xml):
|
||||
"""Filters out keys from XML template that may wary between exports (e.g date or version) and
|
||||
keys that are not imported via this module.
|
||||
|
||||
It is advised that provided XML template exactly matches XML structure used by Zabbix"""
|
||||
# Strip last new line and convert string to ElementTree
|
||||
parsed_xml_root = self.load_xml_template(template_xml.strip())
|
||||
keep_keys = ['graphs', 'templates', 'triggers', 'value_maps']
|
||||
|
||||
# Remove unwanted XML nodes
|
||||
for node in list(parsed_xml_root):
|
||||
if node.tag not in keep_keys:
|
||||
parsed_xml_root.remove(node)
|
||||
|
||||
# Filter empty attributes from template objects to allow accurate comparison
|
||||
for template in list(parsed_xml_root.find('templates')):
|
||||
for element in list(template):
|
||||
if element.text is None and len(list(element)) == 0:
|
||||
template.remove(element)
|
||||
|
||||
# Filter new lines and indentation
|
||||
xml_root_text = list(line.strip() for line in ET.tostring(parsed_xml_root, encoding='utf8', method='xml').decode().split('\n'))
|
||||
return ''.join(xml_root_text)
|
||||
|
||||
def load_json_template(self, template_json, omit_date=False):
|
||||
try:
|
||||
jsondoc = json.loads(template_json)
|
||||
if omit_date and 'date' in jsondoc['zabbix_export']:
|
||||
del jsondoc['zabbix_export']['date']
|
||||
return jsondoc
|
||||
except ValueError as e:
|
||||
self._module.fail_json(msg='Invalid JSON provided', details=to_native(e), exception=traceback.format_exc())
|
||||
|
||||
def load_xml_template(self, template_xml):
|
||||
try:
|
||||
return ET.fromstring(template_xml)
|
||||
except ET.ParseError as e:
|
||||
self._module.fail_json(msg='Invalid XML provided', details=to_native(e), exception=traceback.format_exc())
|
||||
|
||||
def import_template(self, template_content, template_type='json'):
|
||||
# rules schema latest version
|
||||
update_rules = {
|
||||
'applications': {
|
||||
'createMissing': True,
|
||||
'deleteMissing': True
|
||||
},
|
||||
'discoveryRules': {
|
||||
'createMissing': True,
|
||||
'updateExisting': True,
|
||||
'deleteMissing': True
|
||||
},
|
||||
'graphs': {
|
||||
'createMissing': True,
|
||||
'updateExisting': True,
|
||||
'deleteMissing': True
|
||||
},
|
||||
'groups': {
|
||||
'createMissing': True
|
||||
},
|
||||
'httptests': {
|
||||
'createMissing': True,
|
||||
'updateExisting': True,
|
||||
'deleteMissing': True
|
||||
},
|
||||
'items': {
|
||||
'createMissing': True,
|
||||
'updateExisting': True,
|
||||
'deleteMissing': True
|
||||
},
|
||||
'templates': {
|
||||
'createMissing': True,
|
||||
'updateExisting': True
|
||||
},
|
||||
'templateLinkage': {
|
||||
'createMissing': True
|
||||
},
|
||||
'templateScreens': {
|
||||
'createMissing': True,
|
||||
'updateExisting': True,
|
||||
'deleteMissing': True
|
||||
},
|
||||
'triggers': {
|
||||
'createMissing': True,
|
||||
'updateExisting': True,
|
||||
'deleteMissing': True
|
||||
},
|
||||
'valueMaps': {
|
||||
'createMissing': True,
|
||||
'updateExisting': True
|
||||
}
|
||||
}
|
||||
|
||||
try:
|
||||
# old api version support here
|
||||
api_version = self._zapi.api_version()
|
||||
# updateExisting for application removed from zabbix api after 3.2
|
||||
if LooseVersion(api_version).version[:2] <= LooseVersion('3.2').version:
|
||||
update_rules['applications']['updateExisting'] = True
|
||||
|
||||
# templateLinkage.deleteMissing only available in 4.0 branch higher .16 and higher 4.4.4
|
||||
# it's not available in 4.2 branches or lower 4.0.16
|
||||
if LooseVersion(api_version).version[:2] == LooseVersion('4.0').version and \
|
||||
LooseVersion(api_version).version[:3] >= LooseVersion('4.0.16').version:
|
||||
update_rules['templateLinkage']['deleteMissing'] = True
|
||||
if LooseVersion(api_version).version[:3] >= LooseVersion('4.4.4').version:
|
||||
update_rules['templateLinkage']['deleteMissing'] = True
|
||||
|
||||
import_data = {'format': template_type, 'source': template_content, 'rules': update_rules}
|
||||
self._zapi.configuration.import_(import_data)
|
||||
except ZabbixAPIException as e:
|
||||
self._module.fail_json(msg='Unable to import template', details=to_native(e),
|
||||
exception=traceback.format_exc())
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
server_url=dict(type='str', required=True, aliases=['url']),
|
||||
login_user=dict(type='str', required=True),
|
||||
login_password=dict(type='str', required=True, no_log=True),
|
||||
http_login_user=dict(type='str', required=False, default=None),
|
||||
http_login_password=dict(type='str', required=False, default=None, no_log=True),
|
||||
validate_certs=dict(type='bool', required=False, default=True),
|
||||
template_name=dict(type='str', required=False),
|
||||
template_json=dict(type='json', required=False),
|
||||
template_xml=dict(type='str', required=False),
|
||||
template_groups=dict(type='list', required=False),
|
||||
link_templates=dict(type='list', required=False),
|
||||
clear_templates=dict(type='list', required=False),
|
||||
macros=dict(type='list', required=False),
|
||||
omit_date=dict(type='bool', required=False, default=False),
|
||||
dump_format=dict(type='str', required=False, default='json', choices=['json', 'xml']),
|
||||
state=dict(type='str', default="present", choices=['present', 'absent', 'dump']),
|
||||
timeout=dict(type='int', default=10)
|
||||
),
|
||||
required_one_of=[
|
||||
['template_name', 'template_json', 'template_xml']
|
||||
],
|
||||
mutually_exclusive=[
|
||||
['template_name', 'template_json', 'template_xml']
|
||||
],
|
||||
required_if=[
|
||||
['state', 'absent', ['template_name']],
|
||||
['state', 'dump', ['template_name']]
|
||||
],
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
if not HAS_ZABBIX_API:
|
||||
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'), exception=ZBX_IMP_ERR)
|
||||
|
||||
server_url = module.params['server_url']
|
||||
login_user = module.params['login_user']
|
||||
login_password = module.params['login_password']
|
||||
http_login_user = module.params['http_login_user']
|
||||
http_login_password = module.params['http_login_password']
|
||||
validate_certs = module.params['validate_certs']
|
||||
template_name = module.params['template_name']
|
||||
template_json = module.params['template_json']
|
||||
template_xml = module.params['template_xml']
|
||||
template_groups = module.params['template_groups']
|
||||
link_templates = module.params['link_templates']
|
||||
clear_templates = module.params['clear_templates']
|
||||
template_macros = module.params['macros']
|
||||
omit_date = module.params['omit_date']
|
||||
dump_format = module.params['dump_format']
|
||||
state = module.params['state']
|
||||
timeout = module.params['timeout']
|
||||
|
||||
zbx = None
|
||||
try:
|
||||
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
|
||||
validate_certs=validate_certs)
|
||||
zbx.login(login_user, login_password)
|
||||
atexit.register(zbx.logout)
|
||||
except ZabbixAPIException as e:
|
||||
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
|
||||
|
||||
template = Template(module, zbx)
|
||||
|
||||
# Identify template names for IDs retrieval
|
||||
# Template names are expected to reside in ['zabbix_export']['templates'][*]['template'] for both data types
|
||||
template_content, template_type = None, None
|
||||
if template_json is not None:
|
||||
template_type = 'json'
|
||||
template_content = template_json
|
||||
json_parsed = template.load_json_template(template_content)
|
||||
template_names = list(t['template'] for t in json_parsed['zabbix_export']['templates'])
|
||||
|
||||
elif template_xml is not None:
|
||||
template_type = 'xml'
|
||||
template_content = template_xml
|
||||
xml_parsed = template.load_xml_template(template_content)
|
||||
template_names = list(t.find('template').text for t in list(xml_parsed.find('templates')))
|
||||
|
||||
else:
|
||||
template_names = [template_name]
|
||||
|
||||
template_ids = template.get_template_ids(template_names)
|
||||
|
||||
if state == "absent":
|
||||
if not template_ids:
|
||||
module.exit_json(changed=False, msg="Template not found. No changed: %s" % template_name)
|
||||
|
||||
template.delete_template(template_ids)
|
||||
module.exit_json(changed=True, result="Successfully deleted template %s" % template_name)
|
||||
|
||||
elif state == "dump":
|
||||
module.deprecate("The 'dump' state has been deprecated and will be removed, use 'zabbix_template_info' module instead.", version='2.14')
|
||||
if not template_ids:
|
||||
module.fail_json(msg='Template not found: %s' % template_name)
|
||||
|
||||
if dump_format == 'json':
|
||||
module.exit_json(changed=False, template_json=template.dump_template(template_ids, template_type='json', omit_date=omit_date))
|
||||
elif dump_format == 'xml':
|
||||
module.exit_json(changed=False, template_xml=template.dump_template(template_ids, template_type='xml', omit_date=omit_date))
|
||||
|
||||
elif state == "present":
|
||||
# Load all subelements for template that were provided by user
|
||||
group_ids = None
|
||||
if template_groups is not None:
|
||||
group_ids = template.get_group_ids_by_group_names(template_groups)
|
||||
|
||||
link_template_ids = None
|
||||
if link_templates is not None:
|
||||
link_template_ids = template.get_template_ids(link_templates)
|
||||
|
||||
clear_template_ids = None
|
||||
if clear_templates is not None:
|
||||
clear_template_ids = template.get_template_ids(clear_templates)
|
||||
|
||||
if template_macros is not None:
|
||||
# Zabbix configuration.export does not differentiate python types (numbers are returned as strings)
|
||||
for macroitem in template_macros:
|
||||
for key in macroitem:
|
||||
macroitem[key] = str(macroitem[key])
|
||||
|
||||
if not template_ids:
|
||||
# Assume new templates are being added when no ID's were found
|
||||
if template_content is not None:
|
||||
template.import_template(template_content, template_type)
|
||||
module.exit_json(changed=True, result="Template import successful")
|
||||
|
||||
else:
|
||||
if group_ids is None:
|
||||
module.fail_json(msg='template_groups are required when creating a new Zabbix template')
|
||||
|
||||
template.add_template(template_name, group_ids, link_template_ids, template_macros)
|
||||
module.exit_json(changed=True, result="Successfully added template: %s" % template_name)
|
||||
|
||||
else:
|
||||
changed = template.check_template_changed(template_ids, template_groups, link_templates, clear_templates,
|
||||
template_macros, template_content, template_type)
|
||||
|
||||
if module.check_mode:
|
||||
module.exit_json(changed=changed)
|
||||
|
||||
if changed:
|
||||
if template_type is not None:
|
||||
template.import_template(template_content, template_type)
|
||||
else:
|
||||
template.update_template(template_ids, group_ids, link_template_ids, clear_template_ids,
|
||||
template_macros)
|
||||
|
||||
module.exit_json(changed=changed, result="Template successfully updated")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1,273 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright: (c) 2019, sky-joker
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
module: zabbix_template_info
|
||||
short_description: Gather information about Zabbix template
|
||||
author:
|
||||
- sky-joker (@sky-joker)
|
||||
description:
|
||||
- This module allows you to search for Zabbix template.
|
||||
requirements:
|
||||
- "python >= 2.6"
|
||||
- "zabbix-api >= 0.5.4"
|
||||
options:
|
||||
template_name:
|
||||
description:
|
||||
- Name of the template in Zabbix.
|
||||
required: true
|
||||
type: str
|
||||
format:
|
||||
description:
|
||||
- Format to use when dumping template.
|
||||
choices: ['json', 'xml']
|
||||
default: json
|
||||
type: str
|
||||
omit_date:
|
||||
description:
|
||||
- Removes the date field for the dumped template
|
||||
required: false
|
||||
type: bool
|
||||
default: false
|
||||
extends_documentation_fragment:
|
||||
- community.general.zabbix
|
||||
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: Get Zabbix template as JSON
|
||||
zabbix_template_info:
|
||||
server_url: "http://zabbix.example.com/zabbix/"
|
||||
login_user: admin
|
||||
login_password: secret
|
||||
template_name: Template
|
||||
format: json
|
||||
omit_date: yes
|
||||
register: template_json
|
||||
|
||||
- name: Get Zabbix template as XML
|
||||
zabbix_template_info:
|
||||
server_url: "http://zabbix.example.com/zabbix/"
|
||||
login_user: admin
|
||||
login_password: secret
|
||||
template_name: Template
|
||||
format: xml
|
||||
omit_date: no
|
||||
register: template_json
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
---
|
||||
template_json:
|
||||
description: The JSON of the template
|
||||
returned: when format is json and omit_date is true
|
||||
type: str
|
||||
sample: {
|
||||
"zabbix_export": {
|
||||
"version": "4.0",
|
||||
"groups": [
|
||||
{
|
||||
"name": "Templates"
|
||||
}
|
||||
],
|
||||
"templates": [
|
||||
{
|
||||
"template": "Test Template",
|
||||
"name": "Template for Testing",
|
||||
"description": "Testing template import",
|
||||
"groups": [
|
||||
{
|
||||
"name": "Templates"
|
||||
}
|
||||
],
|
||||
"applications": [
|
||||
{
|
||||
"name": "Test Application"
|
||||
}
|
||||
],
|
||||
"items": [],
|
||||
"discovery_rules": [],
|
||||
"httptests": [],
|
||||
"macros": [],
|
||||
"templates": [],
|
||||
"screens": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
template_xml:
|
||||
description: The XML of the template
|
||||
returned: when format is xml and omit_date is false
|
||||
type: str
|
||||
sample: >-
|
||||
<zabbix_export>
|
||||
<version>4.0</version>
|
||||
<date>2019-10-27T14:49:57Z</date>
|
||||
<groups>
|
||||
<group>
|
||||
<name>Templates</name>
|
||||
</group>
|
||||
</groups>
|
||||
<templates>
|
||||
<template>
|
||||
<template>Test Template</template>
|
||||
<name>Template for Testing</name>
|
||||
<description>Testing template import</description>
|
||||
<groups>
|
||||
<group>
|
||||
<name>Templates</name>
|
||||
</group>
|
||||
</groups>
|
||||
<applications>
|
||||
<application>
|
||||
<name>Test Application</name>
|
||||
</application>
|
||||
</applications>
|
||||
<items />
|
||||
<discovery_rules />
|
||||
<httptests />
|
||||
<macros />
|
||||
<templates />
|
||||
<screens />
|
||||
</template>
|
||||
</templates>
|
||||
</zabbix_export>
|
||||
'''
|
||||
|
||||
import atexit
|
||||
import traceback
|
||||
import json
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
try:
|
||||
from zabbix_api import ZabbixAPI
|
||||
from zabbix_api import Already_Exists
|
||||
from zabbix_api import ZabbixAPIException
|
||||
|
||||
HAS_ZABBIX_API = True
|
||||
except ImportError:
|
||||
ZBX_IMP_ERR = traceback.format_exc()
|
||||
HAS_ZABBIX_API = False
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
from ansible.module_utils._text import to_native
|
||||
|
||||
|
||||
class TemplateInfo(object):
|
||||
def __init__(self, module, zbx):
|
||||
self._module = module
|
||||
self._zapi = zbx
|
||||
|
||||
def get_template_id(self, template_name):
|
||||
template_id = []
|
||||
try:
|
||||
template_list = self._zapi.template.get(
|
||||
{
|
||||
'output': 'extend',
|
||||
'filter': {
|
||||
'host': template_name
|
||||
}
|
||||
}
|
||||
)
|
||||
except ZabbixAPIException as e:
|
||||
self._module.fail_json(msg='Failed to get template: %s' % e)
|
||||
|
||||
if template_list:
|
||||
template_id.append(template_list[0]['templateid'])
|
||||
|
||||
return template_id
|
||||
|
||||
def load_json_template(self, template_json, omit_date=False):
|
||||
try:
|
||||
jsondoc = json.loads(template_json)
|
||||
# remove date field if requested
|
||||
if omit_date and 'date' in jsondoc['zabbix_export']:
|
||||
del jsondoc['zabbix_export']['date']
|
||||
return jsondoc
|
||||
except ValueError as e:
|
||||
self._module.fail_json(msg='Invalid JSON provided', details=to_native(e), exception=traceback.format_exc())
|
||||
|
||||
def dump_template(self, template_id, template_type='json', omit_date=False):
|
||||
try:
|
||||
dump = self._zapi.configuration.export({'format': template_type, 'options': {'templates': template_id}})
|
||||
if template_type == 'xml':
|
||||
xmlroot = ET.fromstring(dump.encode('utf-8'))
|
||||
# remove date field if requested
|
||||
if omit_date:
|
||||
date = xmlroot.find(".date")
|
||||
if date is not None:
|
||||
xmlroot.remove(date)
|
||||
return str(ET.tostring(xmlroot, encoding='utf-8').decode('utf-8'))
|
||||
else:
|
||||
return self.load_json_template(dump, omit_date)
|
||||
|
||||
except ZabbixAPIException as e:
|
||||
self._module.fail_json(msg='Unable to export template: %s' % e)
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
server_url=dict(type='str', required=True, aliases=['url']),
|
||||
login_user=dict(type='str', required=True),
|
||||
login_password=dict(type='str', required=True, no_log=True),
|
||||
http_login_user=dict(type='str', required=False, default=None),
|
||||
http_login_password=dict(type='str', required=False, default=None, no_log=True),
|
||||
validate_certs=dict(type='bool', required=False, default=True),
|
||||
timeout=dict(type='int', default=10),
|
||||
template_name=dict(type='str', required=True),
|
||||
omit_date=dict(type='bool', required=False, default=False),
|
||||
format=dict(type='str', choices=['json', 'xml'], default='json')
|
||||
),
|
||||
supports_check_mode=False
|
||||
)
|
||||
|
||||
if not HAS_ZABBIX_API:
|
||||
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'),
|
||||
exception=ZBX_IMP_ERR)
|
||||
|
||||
server_url = module.params['server_url']
|
||||
login_user = module.params['login_user']
|
||||
login_password = module.params['login_password']
|
||||
http_login_user = module.params['http_login_user']
|
||||
http_login_password = module.params['http_login_password']
|
||||
validate_certs = module.params['validate_certs']
|
||||
timeout = module.params['timeout']
|
||||
template_name = module.params['template_name']
|
||||
omit_date = module.params['omit_date']
|
||||
format = module.params['format']
|
||||
|
||||
try:
|
||||
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
|
||||
validate_certs=validate_certs)
|
||||
zbx.login(login_user, login_password)
|
||||
atexit.register(zbx.logout)
|
||||
except Exception as e:
|
||||
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
|
||||
|
||||
template_info = TemplateInfo(module, zbx)
|
||||
|
||||
template_id = template_info.get_template_id(template_name)
|
||||
|
||||
if not template_id:
|
||||
module.fail_json(msg='Template not found: %s' % template_name)
|
||||
|
||||
if format == 'json':
|
||||
module.exit_json(changed=False, template_json=template_info.dump_template(template_id, template_type='json', omit_date=omit_date))
|
||||
elif format == 'xml':
|
||||
module.exit_json(changed=False, template_xml=template_info.dump_template(template_id, template_type='xml', omit_date=omit_date))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,663 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright: (c) 2019, sky-joker
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
module: zabbix_user
|
||||
short_description: Create/update/delete Zabbix users
|
||||
author:
|
||||
- sky-joker (@sky-joker)
|
||||
description:
|
||||
- This module allows you to create, modify and delete Zabbix users.
|
||||
requirements:
|
||||
- "python >= 2.6"
|
||||
- "zabbix-api >= 0.5.4"
|
||||
options:
|
||||
alias:
|
||||
description:
|
||||
- Name of the user alias in Zabbix.
|
||||
- alias is the unique identifier used and cannot be updated using this module.
|
||||
required: true
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- Name of the user.
|
||||
default: ''
|
||||
type: str
|
||||
surname:
|
||||
description:
|
||||
- Surname of the user.
|
||||
default: ''
|
||||
type: str
|
||||
usrgrps:
|
||||
description:
|
||||
- User groups to add the user to.
|
||||
required: true
|
||||
type: list
|
||||
elements: str
|
||||
passwd:
|
||||
description:
|
||||
- User's password.
|
||||
required: true
|
||||
type: str
|
||||
override_passwd:
|
||||
description:
|
||||
- Override password.
|
||||
default: no
|
||||
type: bool
|
||||
lang:
|
||||
description:
|
||||
- Language code of the user's language.
|
||||
default: 'en_GB'
|
||||
choices:
|
||||
- 'en_GB'
|
||||
- 'en_US'
|
||||
- 'zh_CN'
|
||||
- 'cs_CZ'
|
||||
- 'fr_FR'
|
||||
- 'he_IL'
|
||||
- 'it_IT'
|
||||
- 'ko_KR'
|
||||
- 'ja_JP'
|
||||
- 'nb_NO'
|
||||
- 'pl_PL'
|
||||
- 'pt_BR'
|
||||
- 'pt_PT'
|
||||
- 'ru_RU'
|
||||
- 'sk_SK'
|
||||
- 'tr_TR'
|
||||
- 'uk_UA'
|
||||
type: str
|
||||
theme:
|
||||
description:
|
||||
- User's theme.
|
||||
default: 'default'
|
||||
choices:
|
||||
- 'default'
|
||||
- 'blue-theme'
|
||||
- 'dark-theme'
|
||||
type: str
|
||||
autologin:
|
||||
description:
|
||||
- Whether to enable auto-login.
|
||||
- If enable autologin, cannot enable autologout.
|
||||
default: false
|
||||
type: bool
|
||||
autologout:
|
||||
description:
|
||||
- User session life time in seconds. If set to 0, the session will never expire.
|
||||
- If enable autologout, cannot enable autologin.
|
||||
default: '0'
|
||||
type: str
|
||||
refresh:
|
||||
description:
|
||||
- Automatic refresh period in seconds.
|
||||
default: '30'
|
||||
type: str
|
||||
rows_per_page:
|
||||
description:
|
||||
- Amount of object rows to show per page.
|
||||
default: '50'
|
||||
type: str
|
||||
after_login_url:
|
||||
description:
|
||||
- URL of the page to redirect the user to after logging in.
|
||||
default: ''
|
||||
type: str
|
||||
user_medias:
|
||||
description:
|
||||
- Set the user's media.
|
||||
default: []
|
||||
suboptions:
|
||||
mediatype:
|
||||
description:
|
||||
- Media type name to set.
|
||||
default: 'Email'
|
||||
type: str
|
||||
sendto:
|
||||
description:
|
||||
- Address, user name or other identifier of the recipient.
|
||||
required: true
|
||||
type: str
|
||||
period:
|
||||
description:
|
||||
- Time when the notifications can be sent as a time period or user macros separated by a semicolon.
|
||||
- Please review the documentation for more information on the supported time period.
|
||||
- https://www.zabbix.com/documentation/4.0/manual/appendix/time_period
|
||||
default: '1-7,00:00-24:00'
|
||||
type: str
|
||||
severity:
|
||||
description:
|
||||
- Trigger severities to send notifications about.
|
||||
suboptions:
|
||||
not_classified:
|
||||
description:
|
||||
- severity not_classified enable/disable.
|
||||
default: True
|
||||
type: bool
|
||||
information:
|
||||
description:
|
||||
- severity information enable/disable.
|
||||
default: True
|
||||
type: bool
|
||||
warning:
|
||||
description:
|
||||
- severity warning enable/disable.
|
||||
default: True
|
||||
type: bool
|
||||
average:
|
||||
description:
|
||||
- severity average enable/disable.
|
||||
default: True
|
||||
type: bool
|
||||
high:
|
||||
description:
|
||||
- severity high enable/disable.
|
||||
default: True
|
||||
type: bool
|
||||
disaster:
|
||||
description:
|
||||
- severity disaster enable/disable.
|
||||
default: True
|
||||
type: bool
|
||||
default:
|
||||
not_classified: True
|
||||
information: True
|
||||
warning: True
|
||||
average: True
|
||||
high: True
|
||||
disaster: True
|
||||
type: dict
|
||||
active:
|
||||
description:
|
||||
- Whether the media is enabled.
|
||||
default: true
|
||||
type: bool
|
||||
type: list
|
||||
elements: dict
|
||||
type:
|
||||
description:
|
||||
- Type of the user.
|
||||
default: 'Zabbix user'
|
||||
choices:
|
||||
- 'Zabbix user'
|
||||
- 'Zabbix admin'
|
||||
- 'Zabbix super admin'
|
||||
type: str
|
||||
state:
|
||||
description:
|
||||
- State of the user.
|
||||
- On C(present), it will create if user does not exist or update the user if the associated data is different.
|
||||
- On C(absent) will remove a user if it exists.
|
||||
default: 'present'
|
||||
choices: ['present', 'absent']
|
||||
type: str
|
||||
extends_documentation_fragment:
|
||||
- community.general.zabbix
|
||||
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
- name: create of zabbix user.
|
||||
zabbix_user:
|
||||
server_url: "http://zabbix.example.com/zabbix/"
|
||||
login_user: Admin
|
||||
login_password: secret
|
||||
alias: example
|
||||
name: user name
|
||||
surname: user surname
|
||||
usrgrps:
|
||||
- Guests
|
||||
- Disabled
|
||||
passwd: password
|
||||
lang: en_GB
|
||||
theme: blue-theme
|
||||
autologin: no
|
||||
autologout: '0'
|
||||
refresh: '30'
|
||||
rows_per_page: '200'
|
||||
after_login_url: ''
|
||||
user_medias:
|
||||
- mediatype: Email
|
||||
sendto: example@example.com
|
||||
period: 1-7,00:00-24:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: yes
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: no
|
||||
type: Zabbix super admin
|
||||
state: present
|
||||
|
||||
- name: delete of zabbix user.
|
||||
zabbix_user:
|
||||
server_url: "http://zabbix.example.com/zabbix/"
|
||||
login_user: admin
|
||||
login_password: secret
|
||||
alias: example
|
||||
usrgrps:
|
||||
- Guests
|
||||
passwd: password
|
||||
user_medias:
|
||||
- sendto: example@example.com
|
||||
state: absent
|
||||
'''
|
||||
|
||||
RETURN = r'''
|
||||
user_ids:
|
||||
description: User id created or changed
|
||||
returned: success
|
||||
type: dict
|
||||
sample: { "userids": [ "5" ] }
|
||||
'''
|
||||
|
||||
import atexit
|
||||
import traceback
|
||||
|
||||
try:
|
||||
from zabbix_api import ZabbixAPI
|
||||
from zabbix_api import Already_Exists
|
||||
|
||||
HAS_ZABBIX_API = True
|
||||
except ImportError:
|
||||
ZBX_IMP_ERR = traceback.format_exc()
|
||||
HAS_ZABBIX_API = False
|
||||
|
||||
from distutils.version import LooseVersion
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
import copy
|
||||
|
||||
|
||||
class User(object):
|
||||
def __init__(self, module, zbx):
|
||||
self._module = module
|
||||
self._zapi = zbx
|
||||
self._zbx_api_version = zbx.api_version()[:3]
|
||||
|
||||
def get_usergroupid_by_user_group_name(self, usrgrps):
|
||||
user_group_ids = []
|
||||
for user_group_name in usrgrps:
|
||||
user_group = self._zapi.usergroup.get({'output': 'extend', 'filter': {'name': user_group_name}})
|
||||
if user_group:
|
||||
user_group_ids.append({'usrgrpid': user_group[0]['usrgrpid']})
|
||||
else:
|
||||
self._module.fail_json(msg="User group not found: %s" % user_group_name)
|
||||
return user_group_ids
|
||||
|
||||
def check_user_exist(self, alias):
|
||||
zbx_user = self._zapi.user.get({'output': 'extend', 'filter': {'alias': alias},
|
||||
'getAccess': True, 'selectMedias': 'extend',
|
||||
'selectUsrgrps': 'extend'})
|
||||
|
||||
return zbx_user
|
||||
|
||||
def convert_user_medias_parameter_types(self, user_medias):
|
||||
copy_user_medias = copy.deepcopy(user_medias)
|
||||
for user_media in copy_user_medias:
|
||||
media_types = self._zapi.mediatype.get({'output': 'extend'})
|
||||
for media_type in media_types:
|
||||
if LooseVersion(self._zbx_api_version) < LooseVersion('4.4'):
|
||||
if media_type['description'] == user_media['mediatype']:
|
||||
user_media['mediatypeid'] = media_type['mediatypeid']
|
||||
break
|
||||
else:
|
||||
if media_type['name'] == user_media['mediatype']:
|
||||
user_media['mediatypeid'] = media_type['mediatypeid']
|
||||
break
|
||||
|
||||
if 'mediatypeid' not in user_media:
|
||||
self._module.fail_json(msg="Media type not found: %s" % user_media['mediatype'])
|
||||
else:
|
||||
del user_media['mediatype']
|
||||
|
||||
severity_binary_number = ''
|
||||
for severity_key in 'disaster', 'high', 'average', 'warning', 'information', 'not_classified':
|
||||
if user_media['severity'][severity_key]:
|
||||
severity_binary_number = severity_binary_number + '1'
|
||||
else:
|
||||
severity_binary_number = severity_binary_number + '0'
|
||||
user_media['severity'] = str(int(severity_binary_number, 2))
|
||||
|
||||
if user_media['active']:
|
||||
user_media['active'] = '0'
|
||||
else:
|
||||
user_media['active'] = '1'
|
||||
|
||||
return copy_user_medias
|
||||
|
||||
def user_parameter_difference_check(self, zbx_user, alias, name, surname, user_group_ids, passwd, lang, theme,
|
||||
autologin, autologout, refresh, rows_per_page, url, user_medias, user_type,
|
||||
override_passwd):
|
||||
|
||||
user_medias = self.convert_user_medias_parameter_types(user_medias)
|
||||
|
||||
# existing data
|
||||
existing_data = copy.deepcopy(zbx_user[0])
|
||||
usrgrpids = []
|
||||
for usrgrp in existing_data['usrgrps']:
|
||||
usrgrpids.append({'usrgrpid': usrgrp['usrgrpid']})
|
||||
|
||||
existing_data['usrgrps'] = sorted(usrgrpids, key=lambda x: x['usrgrpid'])
|
||||
|
||||
# Processing for zabbix 4.0 and above.
|
||||
# In zabbix 4.0 and above, Email sendto is of type list.
|
||||
# This module, one media supports only one Email sendto.
|
||||
# Therefore following processing extract one Email from list.
|
||||
if LooseVersion(self._zbx_api_version) >= LooseVersion('4.0'):
|
||||
for media in existing_data['medias']:
|
||||
if isinstance(media['sendto'], list):
|
||||
media['sendto'] = media['sendto'][0]
|
||||
|
||||
existing_data['user_medias'] = sorted(existing_data['medias'], key=lambda x: x['sendto'])
|
||||
for del_key in ['medias', 'attempt_clock', 'attempt_failed', 'attempt_ip', 'debug_mode', 'users_status',
|
||||
'gui_access']:
|
||||
del existing_data[del_key]
|
||||
|
||||
for user_media in existing_data['user_medias']:
|
||||
for del_key in ['mediaid', 'userid']:
|
||||
del user_media[del_key]
|
||||
|
||||
# request data
|
||||
request_data = {
|
||||
'userid': zbx_user[0]['userid'],
|
||||
'alias': alias,
|
||||
'name': name,
|
||||
'surname': surname,
|
||||
'usrgrps': sorted(user_group_ids, key=lambda x: x['usrgrpid']),
|
||||
'lang': lang,
|
||||
'theme': theme,
|
||||
'autologin': autologin,
|
||||
'autologout': autologout,
|
||||
'refresh': refresh,
|
||||
'rows_per_page': rows_per_page,
|
||||
'url': url,
|
||||
'user_medias': sorted(user_medias, key=lambda x: x['sendto']),
|
||||
'type': user_type
|
||||
}
|
||||
|
||||
if override_passwd:
|
||||
request_data['passwd'] = passwd
|
||||
|
||||
user_parameter_difference_check_result = True
|
||||
if existing_data == request_data:
|
||||
user_parameter_difference_check_result = False
|
||||
|
||||
diff_params = {
|
||||
"before": existing_data,
|
||||
"after": request_data
|
||||
}
|
||||
|
||||
return user_parameter_difference_check_result, diff_params
|
||||
|
||||
def add_user(self, alias, name, surname, user_group_ids, passwd, lang, theme, autologin, autologout, refresh,
|
||||
rows_per_page, url, user_medias, user_type):
|
||||
|
||||
user_medias = self.convert_user_medias_parameter_types(user_medias)
|
||||
|
||||
user_ids = {}
|
||||
|
||||
request_data = {
|
||||
'alias': alias,
|
||||
'name': name,
|
||||
'surname': surname,
|
||||
'usrgrps': user_group_ids,
|
||||
'passwd': passwd,
|
||||
'lang': lang,
|
||||
'theme': theme,
|
||||
'autologin': autologin,
|
||||
'autologout': autologout,
|
||||
'refresh': refresh,
|
||||
'rows_per_page': rows_per_page,
|
||||
'url': url,
|
||||
'user_medias': user_medias,
|
||||
'type': user_type
|
||||
}
|
||||
|
||||
diff_params = {}
|
||||
if not self._module.check_mode:
|
||||
try:
|
||||
user_ids = self._zapi.user.create(request_data)
|
||||
except Exception as e:
|
||||
self._module.fail_json(msg="Failed to create user %s: %s" % (alias, e))
|
||||
else:
|
||||
diff_params = {
|
||||
"before": "",
|
||||
"after": request_data
|
||||
}
|
||||
|
||||
return user_ids, diff_params
|
||||
|
||||
def update_user(self, zbx_user, alias, name, surname, user_group_ids, passwd, lang, theme, autologin, autologout,
|
||||
refresh, rows_per_page, url, user_medias, user_type, override_passwd):
|
||||
|
||||
user_medias = self.convert_user_medias_parameter_types(user_medias)
|
||||
|
||||
user_ids = {}
|
||||
|
||||
request_data = {
|
||||
'userid': zbx_user[0]['userid'],
|
||||
'alias': alias,
|
||||
'name': name,
|
||||
'surname': surname,
|
||||
'usrgrps': user_group_ids,
|
||||
'lang': lang,
|
||||
'theme': theme,
|
||||
'autologin': autologin,
|
||||
'autologout': autologout,
|
||||
'refresh': refresh,
|
||||
'rows_per_page': rows_per_page,
|
||||
'url': url,
|
||||
'type': user_type
|
||||
}
|
||||
|
||||
if override_passwd:
|
||||
request_data['passwd'] = passwd
|
||||
|
||||
# In the case of zabbix 3.2 or less, it is necessary to use updatemedia method to update media.
|
||||
if LooseVersion(self._zbx_api_version) <= LooseVersion('3.2'):
|
||||
try:
|
||||
user_ids = self._zapi.user.update(request_data)
|
||||
except Exception as e:
|
||||
self._module.fail_json(msg="Failed to update user %s: %s" % (alias, e))
|
||||
|
||||
try:
|
||||
user_ids = self._zapi.user.updatemedia({
|
||||
'users': [{'userid': zbx_user[0]['userid']}],
|
||||
'medias': user_medias
|
||||
})
|
||||
except Exception as e:
|
||||
self._module.fail_json(msg="Failed to update user medias %s: %s" % (alias, e))
|
||||
|
||||
if LooseVersion(self._zbx_api_version) >= LooseVersion('3.4'):
|
||||
try:
|
||||
request_data['user_medias'] = user_medias
|
||||
user_ids = self._zapi.user.update(request_data)
|
||||
except Exception as e:
|
||||
self._module.fail_json(msg="Failed to update user %s: %s" % (alias, e))
|
||||
|
||||
return user_ids
|
||||
|
||||
def delete_user(self, zbx_user, alias):
|
||||
user_ids = {}
|
||||
diff_params = {}
|
||||
|
||||
if not self._module.check_mode:
|
||||
try:
|
||||
user_ids = self._zapi.user.delete([zbx_user[0]['userid']])
|
||||
except Exception as e:
|
||||
self._module.fail_json(msg="Failed to delete user %s: %s" % (alias, e))
|
||||
else:
|
||||
diff_params = {
|
||||
"before": zbx_user[0],
|
||||
"after": ""
|
||||
}
|
||||
|
||||
return user_ids, diff_params
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
server_url=dict(type='str', required=True, aliases=['url']),
|
||||
login_user=dict(type='str', required=True),
|
||||
login_password=dict(type='str', required=True, no_log=True),
|
||||
http_login_user=dict(type='str', required=False, default=None),
|
||||
http_login_password=dict(type='str', required=False, default=None, no_log=True),
|
||||
validate_certs=dict(type='bool', required=False, default=True),
|
||||
alias=dict(type='str', required=True),
|
||||
name=dict(type='str', default=''),
|
||||
surname=dict(type='str', default=''),
|
||||
usrgrps=dict(type='list', required=True),
|
||||
passwd=dict(type='str', required=True, no_log=True),
|
||||
override_passwd=dict(type='bool', required=False, default=False),
|
||||
lang=dict(type='str', default='en_GB', choices=['en_GB', 'en_US', 'zh_CN', 'cs_CZ', 'fr_FR',
|
||||
'he_IL', 'it_IT', 'ko_KR', 'ja_JP', 'nb_NO',
|
||||
'pl_PL', 'pt_BR', 'pt_PT', 'ru_RU', 'sk_SK',
|
||||
'tr_TR', 'uk_UA']),
|
||||
theme=dict(type='str', default='default', choices=['default', 'blue-theme', 'dark-theme']),
|
||||
autologin=dict(type='bool', default=False),
|
||||
autologout=dict(type='str', default='0'),
|
||||
refresh=dict(type='str', default='30'),
|
||||
rows_per_page=dict(type='str', default='50'),
|
||||
after_login_url=dict(type='str', default=''),
|
||||
user_medias=dict(type='list', default=[],
|
||||
elements='dict',
|
||||
options=dict(
|
||||
mediatype=dict(type='str', default='Email'),
|
||||
sendto=dict(type='str', required=True),
|
||||
period=dict(type='str', default='1-7,00:00-24:00'),
|
||||
severity=dict(type='dict',
|
||||
options=dict(
|
||||
not_classified=dict(type='bool', default=True),
|
||||
information=dict(type='bool', default=True),
|
||||
warning=dict(type='bool', default=True),
|
||||
average=dict(type='bool', default=True),
|
||||
high=dict(type='bool', default=True),
|
||||
disaster=dict(type='bool', default=True)),
|
||||
default=dict(
|
||||
not_classified=True,
|
||||
information=True,
|
||||
warning=True,
|
||||
average=True,
|
||||
high=True,
|
||||
disaster=True
|
||||
)),
|
||||
active=dict(type='bool', default=True)
|
||||
)),
|
||||
type=dict(type='str', default='Zabbix user', choices=['Zabbix user', 'Zabbix admin', 'Zabbix super admin']),
|
||||
state=dict(type='str', default="present", choices=['present', 'absent']),
|
||||
timeout=dict(type='int', default=10)
|
||||
),
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
if not HAS_ZABBIX_API:
|
||||
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'),
|
||||
exception=ZBX_IMP_ERR)
|
||||
|
||||
server_url = module.params['server_url']
|
||||
login_user = module.params['login_user']
|
||||
login_password = module.params['login_password']
|
||||
http_login_user = module.params['http_login_user']
|
||||
http_login_password = module.params['http_login_password']
|
||||
validate_certs = module.params['validate_certs']
|
||||
alias = module.params['alias']
|
||||
name = module.params['name']
|
||||
surname = module.params['surname']
|
||||
usrgrps = module.params['usrgrps']
|
||||
passwd = module.params['passwd']
|
||||
override_passwd = module.params['override_passwd']
|
||||
lang = module.params['lang']
|
||||
theme = module.params['theme']
|
||||
autologin = module.params['autologin']
|
||||
autologout = module.params['autologout']
|
||||
refresh = module.params['refresh']
|
||||
rows_per_page = module.params['rows_per_page']
|
||||
after_login_url = module.params['after_login_url']
|
||||
user_medias = module.params['user_medias']
|
||||
user_type = module.params['type']
|
||||
state = module.params['state']
|
||||
timeout = module.params['timeout']
|
||||
|
||||
if autologin:
|
||||
autologin = '1'
|
||||
else:
|
||||
autologin = '0'
|
||||
|
||||
user_type_dict = {
|
||||
'Zabbix user': '1',
|
||||
'Zabbix admin': '2',
|
||||
'Zabbix super admin': '3'
|
||||
}
|
||||
user_type = user_type_dict[user_type]
|
||||
|
||||
zbx = None
|
||||
|
||||
# login to zabbix
|
||||
try:
|
||||
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
|
||||
validate_certs=validate_certs)
|
||||
zbx.login(login_user, login_password)
|
||||
atexit.register(zbx.logout)
|
||||
except Exception as e:
|
||||
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
|
||||
|
||||
user = User(module, zbx)
|
||||
|
||||
user_ids = {}
|
||||
zbx_user = user.check_user_exist(alias)
|
||||
if state == 'present':
|
||||
user_group_ids = user.get_usergroupid_by_user_group_name(usrgrps)
|
||||
if zbx_user:
|
||||
diff_check_result, diff_params = user.user_parameter_difference_check(zbx_user, alias, name, surname,
|
||||
user_group_ids, passwd, lang, theme,
|
||||
autologin, autologout, refresh,
|
||||
rows_per_page, after_login_url,
|
||||
user_medias, user_type,
|
||||
override_passwd)
|
||||
|
||||
if not module.check_mode and diff_check_result:
|
||||
user_ids = user.update_user(zbx_user, alias, name, surname, user_group_ids, passwd, lang,
|
||||
theme, autologin, autologout, refresh, rows_per_page, after_login_url,
|
||||
user_medias, user_type, override_passwd)
|
||||
else:
|
||||
diff_check_result = True
|
||||
user_ids, diff_params = user.add_user(alias, name, surname, user_group_ids, passwd, lang, theme, autologin,
|
||||
autologout, refresh, rows_per_page, after_login_url, user_medias,
|
||||
user_type)
|
||||
|
||||
if state == 'absent':
|
||||
if zbx_user:
|
||||
diff_check_result = True
|
||||
user_ids, diff_params = user.delete_user(zbx_user, alias)
|
||||
else:
|
||||
diff_check_result = False
|
||||
diff_params = {}
|
||||
|
||||
if not module.check_mode:
|
||||
if user_ids:
|
||||
module.exit_json(changed=True, user_ids=user_ids)
|
||||
else:
|
||||
module.exit_json(changed=False)
|
||||
else:
|
||||
if diff_check_result:
|
||||
module.exit_json(changed=True, diff=diff_params)
|
||||
else:
|
||||
module.exit_json(changed=False, diff=diff_params)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,175 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright: (c) 2019, sky-joker
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
module: zabbix_user_info
|
||||
short_description: Gather information about Zabbix user
|
||||
author:
|
||||
- sky-joker (@sky-joker)
|
||||
description:
|
||||
- This module allows you to search for Zabbix user entries.
|
||||
requirements:
|
||||
- "python >= 2.6"
|
||||
- "zabbix-api >= 0.5.4"
|
||||
options:
|
||||
alias:
|
||||
description:
|
||||
- Name of the user alias in Zabbix.
|
||||
required: true
|
||||
type: str
|
||||
extends_documentation_fragment:
|
||||
- community.general.zabbix
|
||||
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: Get zabbix user info
|
||||
zabbix_user_info:
|
||||
server_url: "http://zabbix.example.com/zabbix/"
|
||||
login_user: admin
|
||||
login_password: secret
|
||||
alias: example
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
zabbix_user:
|
||||
description: example
|
||||
returned: always
|
||||
type: dict
|
||||
sample: {
|
||||
"alias": "example",
|
||||
"attempt_clock": "0",
|
||||
"attempt_failed": "0",
|
||||
"attempt_ip": "",
|
||||
"autologin": "0",
|
||||
"autologout": "0",
|
||||
"debug_mode": "0",
|
||||
"gui_access": "0",
|
||||
"lang": "en_GB",
|
||||
"medias": [
|
||||
{
|
||||
"active": "0",
|
||||
"mediaid": "668",
|
||||
"mediatypeid": "1",
|
||||
"period": "1-7,00:00-24:00",
|
||||
"sendto": "example@example.com",
|
||||
"severity": "63",
|
||||
"userid": "660"
|
||||
}
|
||||
],
|
||||
"name": "user",
|
||||
"refresh": "30s",
|
||||
"rows_per_page": "50",
|
||||
"surname": "example",
|
||||
"theme": "default",
|
||||
"type": "1",
|
||||
"url": "",
|
||||
"userid": "660",
|
||||
"users_status": "0",
|
||||
"usrgrps": [
|
||||
{
|
||||
"debug_mode": "0",
|
||||
"gui_access": "0",
|
||||
"name": "Guests",
|
||||
"users_status": "0",
|
||||
"usrgrpid": "8"
|
||||
}
|
||||
]
|
||||
}
|
||||
'''
|
||||
|
||||
import atexit
|
||||
import traceback
|
||||
|
||||
try:
|
||||
from zabbix_api import ZabbixAPI
|
||||
|
||||
HAS_ZABBIX_API = True
|
||||
except ImportError:
|
||||
ZBX_IMP_ERR = traceback.format_exc()
|
||||
HAS_ZABBIX_API = False
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
|
||||
|
||||
class User(object):
|
||||
def __init__(self, module, zbx):
|
||||
self._module = module
|
||||
self._zapi = zbx
|
||||
|
||||
def get_user_by_user_alias(self, alias):
|
||||
zabbix_user = ""
|
||||
try:
|
||||
zabbix_user = self._zapi.user.get({'output': 'extend', 'filter': {'alias': alias},
|
||||
'getAccess': True, 'selectMedias': 'extend',
|
||||
'selectUsrgrps': 'extend'})
|
||||
except Exception as e:
|
||||
self._zapi.logout()
|
||||
self._module.fail_json(msg="Failed to get user information: %s" % e)
|
||||
|
||||
if not zabbix_user:
|
||||
zabbix_user = {}
|
||||
else:
|
||||
zabbix_user = zabbix_user[0]
|
||||
|
||||
return zabbix_user
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
server_url=dict(type='str', required=True, aliases=['url']),
|
||||
login_user=dict(type='str', required=True),
|
||||
login_password=dict(type='str', required=True, no_log=True),
|
||||
http_login_user=dict(type='str', required=False, default=None),
|
||||
http_login_password=dict(type='str', required=False, default=None, no_log=True),
|
||||
validate_certs=dict(type='bool', required=False, default=True),
|
||||
alias=dict(type='str', required=True),
|
||||
timeout=dict(type='int', default=10)
|
||||
),
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
if not HAS_ZABBIX_API:
|
||||
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'),
|
||||
exception=ZBX_IMP_ERR)
|
||||
|
||||
server_url = module.params['server_url']
|
||||
login_user = module.params['login_user']
|
||||
login_password = module.params['login_password']
|
||||
http_login_user = module.params['http_login_user']
|
||||
http_login_password = module.params['http_login_password']
|
||||
validate_certs = module.params['validate_certs']
|
||||
alias = module.params['alias']
|
||||
timeout = module.params['timeout']
|
||||
|
||||
zbx = None
|
||||
|
||||
# login to zabbix
|
||||
try:
|
||||
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
|
||||
validate_certs=validate_certs)
|
||||
zbx.login(login_user, login_password)
|
||||
atexit.register(zbx.logout)
|
||||
except Exception as e:
|
||||
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
|
||||
|
||||
user = User(module, zbx)
|
||||
zabbix_user = user.get_user_by_user_alias(alias)
|
||||
zbx.logout()
|
||||
module.exit_json(changed=False, zabbix_user=zabbix_user)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,339 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# (c) 2019, Ruben Tsirunyan <rubentsirunyan@gmail.com>
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: zabbix_valuemap
|
||||
short_description: Create/update/delete Zabbix value maps
|
||||
description:
|
||||
- This module allows you to create, modify and delete Zabbix value maps.
|
||||
author:
|
||||
- "Ruben Tsirunyan (@rubentsirunyan)"
|
||||
requirements:
|
||||
- "zabbix-api >= 0.5.4"
|
||||
options:
|
||||
name:
|
||||
type: 'str'
|
||||
description:
|
||||
- Name of the value map.
|
||||
required: true
|
||||
state:
|
||||
type: 'str'
|
||||
description:
|
||||
- State of the value map.
|
||||
- On C(present), it will create a value map if it does not exist or update the value map if the associated data is different.
|
||||
- On C(absent), it will remove the value map if it exists.
|
||||
choices: ['present', 'absent']
|
||||
default: 'present'
|
||||
mappings:
|
||||
type: 'list'
|
||||
elements: dict
|
||||
description:
|
||||
- List of value mappings for the value map.
|
||||
- Required when I(state=present).
|
||||
suboptions:
|
||||
value:
|
||||
type: 'str'
|
||||
description: Original value.
|
||||
required: true
|
||||
map_to:
|
||||
type: 'str'
|
||||
description: Value to which the original value is mapped to.
|
||||
required: true
|
||||
|
||||
extends_documentation_fragment:
|
||||
- community.general.zabbix
|
||||
|
||||
'''
|
||||
|
||||
RETURN = r'''
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
- name: Create a value map
|
||||
local_action:
|
||||
module: zabbix_valuemap
|
||||
server_url: http://zabbix.example.com
|
||||
login_user: username
|
||||
login_password: password
|
||||
name: Numbers
|
||||
mappings:
|
||||
- value: 1
|
||||
map_to: one
|
||||
- value: 2
|
||||
map_to: two
|
||||
state: present
|
||||
'''
|
||||
|
||||
|
||||
import atexit
|
||||
import traceback
|
||||
|
||||
try:
|
||||
from zabbix_api import ZabbixAPI
|
||||
HAS_ZABBIX_API = True
|
||||
except ImportError:
|
||||
ZBX_IMP_ERR = traceback.format_exc()
|
||||
HAS_ZABBIX_API = False
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
|
||||
|
||||
def construct_parameters(**kwargs):
|
||||
"""Translates data to a format suitable for Zabbix API
|
||||
|
||||
Args:
|
||||
**kwargs: Arguments passed to the module.
|
||||
|
||||
Returns:
|
||||
A dictionary of arguments in a format that is understandable by Zabbix API.
|
||||
"""
|
||||
if kwargs['mappings'] is None:
|
||||
return dict(
|
||||
name=kwargs['name']
|
||||
)
|
||||
return dict(
|
||||
name=kwargs['name'],
|
||||
mappings=[
|
||||
dict(
|
||||
value=mapping['value'],
|
||||
newvalue=mapping['map_to']
|
||||
) for mapping in kwargs['mappings']
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def check_if_valuemap_exists(module, zbx, name):
|
||||
"""Checks if value map exists.
|
||||
|
||||
Args:
|
||||
module: AnsibleModule object
|
||||
zbx: ZabbixAPI object
|
||||
name: Zabbix valuemap name
|
||||
|
||||
Returns:
|
||||
tuple: First element is True if valuemap exists and False otherwise.
|
||||
Second element is a dictionary of valuemap object if it exists.
|
||||
"""
|
||||
try:
|
||||
valuemap_list = zbx.valuemap.get({
|
||||
'output': 'extend',
|
||||
'selectMappings': 'extend',
|
||||
'filter': {'name': [name]}
|
||||
})
|
||||
if len(valuemap_list) < 1:
|
||||
return False, None
|
||||
else:
|
||||
return True, valuemap_list[0]
|
||||
except Exception as e:
|
||||
module.fail_json(msg="Failed to get ID of the valuemap '{name}': {e}".format(name=name, e=e))
|
||||
|
||||
|
||||
def diff(existing, new):
|
||||
"""Constructs the diff for Ansible's --diff option.
|
||||
|
||||
Args:
|
||||
existing (dict): Existing valuemap data.
|
||||
new (dict): New valuemap data.
|
||||
|
||||
Returns:
|
||||
A dictionary like {'before': existing, 'after': new}
|
||||
with filtered empty values.
|
||||
"""
|
||||
before = {}
|
||||
after = {}
|
||||
for key in new:
|
||||
before[key] = existing[key]
|
||||
if new[key] is None:
|
||||
after[key] = ''
|
||||
else:
|
||||
after[key] = new[key]
|
||||
return {'before': before, 'after': after}
|
||||
|
||||
|
||||
def get_update_params(module, zbx, existing_valuemap, **kwargs):
|
||||
"""Filters only the parameters that are different and need to be updated.
|
||||
|
||||
Args:
|
||||
module: AnsibleModule object.
|
||||
zbx: ZabbixAPI object.
|
||||
existing_valuemap (dict): Existing valuemap.
|
||||
**kwargs: Parameters for the new valuemap.
|
||||
|
||||
Returns:
|
||||
A tuple where the first element is a dictionary of parameters
|
||||
that need to be updated and the second one is a dictionary
|
||||
returned by diff() function with
|
||||
existing valuemap data and new params passed to it.
|
||||
"""
|
||||
|
||||
params_to_update = {}
|
||||
if sorted(existing_valuemap['mappings'], key=lambda k: k['value']) != sorted(kwargs['mappings'], key=lambda k: k['value']):
|
||||
params_to_update['mappings'] = kwargs['mappings']
|
||||
return params_to_update, diff(existing_valuemap, kwargs)
|
||||
|
||||
|
||||
def delete_valuemap(module, zbx, valuemap_id):
|
||||
try:
|
||||
return zbx.valuemap.delete([valuemap_id])
|
||||
except Exception as e:
|
||||
module.fail_json(msg="Failed to delete valuemap '{_id}': {e}".format(_id=valuemap_id, e=e))
|
||||
|
||||
|
||||
def update_valuemap(module, zbx, **kwargs):
|
||||
try:
|
||||
valuemap_id = zbx.valuemap.update(kwargs)
|
||||
except Exception as e:
|
||||
module.fail_json(msg="Failed to update valuemap '{_id}': {e}".format(_id=kwargs['valuemapid'], e=e))
|
||||
|
||||
|
||||
def create_valuemap(module, zbx, **kwargs):
|
||||
try:
|
||||
valuemap_id = zbx.valuemap.create(kwargs)
|
||||
except Exception as e:
|
||||
module.fail_json(msg="Failed to create valuemap '{name}': {e}".format(name=kwargs['description'], e=e))
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
server_url=dict(type='str', required=True, aliases=['url']),
|
||||
login_user=dict(type='str', required=True),
|
||||
login_password=dict(type='str', required=True, no_log=True),
|
||||
http_login_user=dict(type='str', required=False, default=None),
|
||||
http_login_password=dict(type='str', required=False, default=None, no_log=True),
|
||||
validate_certs=dict(type='bool', required=False, default=True),
|
||||
name=dict(type='str', required=True),
|
||||
state=dict(type='str', default='present', choices=['present', 'absent']),
|
||||
mappings=dict(
|
||||
type='list',
|
||||
elements='dict',
|
||||
options=dict(
|
||||
value=dict(type='str', required=True),
|
||||
map_to=dict(type='str', required=True)
|
||||
)
|
||||
),
|
||||
timeout=dict(type='int', default=10)
|
||||
),
|
||||
supports_check_mode=True,
|
||||
required_if=[
|
||||
['state', 'present', ['mappings']],
|
||||
]
|
||||
)
|
||||
|
||||
if not HAS_ZABBIX_API:
|
||||
module.fail_json(msg=missing_required_lib('zabbix-api', url='https://pypi.org/project/zabbix-api/'), exception=ZBX_IMP_ERR)
|
||||
|
||||
server_url = module.params['server_url']
|
||||
login_user = module.params['login_user']
|
||||
login_password = module.params['login_password']
|
||||
http_login_user = module.params['http_login_user']
|
||||
http_login_password = module.params['http_login_password']
|
||||
validate_certs = module.params['validate_certs']
|
||||
name = module.params['name']
|
||||
state = module.params['state']
|
||||
mappings = module.params['mappings']
|
||||
timeout = module.params['timeout']
|
||||
|
||||
zbx = None
|
||||
# login to zabbix
|
||||
try:
|
||||
zbx = ZabbixAPI(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
|
||||
validate_certs=validate_certs)
|
||||
zbx.login(login_user, login_password)
|
||||
atexit.register(zbx.logout)
|
||||
except Exception as e:
|
||||
module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)
|
||||
|
||||
valuemap_exists, valuemap_object = check_if_valuemap_exists(module, zbx, name)
|
||||
|
||||
parameters = construct_parameters(
|
||||
name=name,
|
||||
mappings=mappings
|
||||
)
|
||||
|
||||
if valuemap_exists:
|
||||
valuemap_id = valuemap_object['valuemapid']
|
||||
if state == 'absent':
|
||||
if module.check_mode:
|
||||
module.exit_json(
|
||||
changed=True,
|
||||
msg="Value map would have been deleted. Name: {name}, ID: {_id}".format(
|
||||
name=name,
|
||||
_id=valuemap_id
|
||||
)
|
||||
)
|
||||
valuemap_id = delete_valuemap(module, zbx, valuemap_id)
|
||||
module.exit_json(
|
||||
changed=True,
|
||||
msg="Value map deleted. Name: {name}, ID: {_id}".format(
|
||||
name=name,
|
||||
_id=valuemap_id
|
||||
)
|
||||
)
|
||||
else:
|
||||
params_to_update, diff = get_update_params(module, zbx, valuemap_object, **parameters)
|
||||
if params_to_update == {}:
|
||||
module.exit_json(
|
||||
changed=False,
|
||||
msg="Value map is up to date: {name}".format(name=name)
|
||||
)
|
||||
else:
|
||||
if module.check_mode:
|
||||
module.exit_json(
|
||||
changed=True,
|
||||
diff=diff,
|
||||
msg="Value map would have been updated. Name: {name}, ID: {_id}".format(
|
||||
name=name,
|
||||
_id=valuemap_id
|
||||
)
|
||||
)
|
||||
valuemap_id = update_valuemap(
|
||||
module, zbx,
|
||||
valuemapid=valuemap_id,
|
||||
**params_to_update
|
||||
)
|
||||
module.exit_json(
|
||||
changed=True,
|
||||
diff=diff,
|
||||
msg="Value map updated. Name: {name}, ID: {_id}".format(
|
||||
name=name,
|
||||
_id=valuemap_id
|
||||
)
|
||||
)
|
||||
else:
|
||||
if state == "absent":
|
||||
module.exit_json(changed=False)
|
||||
else:
|
||||
if module.check_mode:
|
||||
module.exit_json(
|
||||
changed=True,
|
||||
msg="Value map would have been created. Name: {name}, ID: {_id}".format(
|
||||
name=name,
|
||||
_id=valuemap_id
|
||||
)
|
||||
)
|
||||
valuemap_id = create_valuemap(module, zbx, **parameters)
|
||||
module.exit_json(
|
||||
changed=True,
|
||||
msg="Value map created: {name}, ID: {_id}".format(
|
||||
name=name,
|
||||
_id=valuemap_id
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1,20 +0,0 @@
|
|||
# Ansible Zabbix external inventory script settings
|
||||
#
|
||||
|
||||
[zabbix]
|
||||
|
||||
# Server location
|
||||
server = http://zabbix.example.com/zabbix
|
||||
|
||||
# Login
|
||||
username = admin
|
||||
password = zabbix
|
||||
|
||||
# Verify the server's SSL certificate
|
||||
validate_certs = True
|
||||
|
||||
# Read zabbix inventory per host
|
||||
read_host_inventory = True
|
||||
|
||||
# Set ansible_ssh_host based on first interface settings
|
||||
use_host_interface = True
|
|
@ -1,196 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# (c) 2013, Greg Buehler
|
||||
# (c) 2018, Filippo Ferrazini
|
||||
#
|
||||
# This file is part of Ansible,
|
||||
#
|
||||
# Ansible is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Ansible is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
######################################################################
|
||||
|
||||
"""
|
||||
Zabbix Server external inventory script.
|
||||
========================================
|
||||
|
||||
Returns hosts and hostgroups from Zabbix Server.
|
||||
If you want to run with --limit against a host group with space in the
|
||||
name, use asterisk. For example --limit="Linux*servers".
|
||||
|
||||
Configuration is read from `zabbix.ini`.
|
||||
|
||||
Tested with Zabbix Server 2.0.6, 3.2.3 and 3.4.
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
import argparse
|
||||
from ansible.module_utils.six.moves import configparser
|
||||
|
||||
try:
|
||||
from zabbix_api import ZabbixAPI
|
||||
except Exception:
|
||||
print("Error: Zabbix API library must be installed: pip install zabbix-api.",
|
||||
file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
import json
|
||||
|
||||
|
||||
class ZabbixInventory(object):
|
||||
|
||||
def read_settings(self):
|
||||
config = configparser.SafeConfigParser()
|
||||
conf_path = './zabbix.ini'
|
||||
if not os.path.exists(conf_path):
|
||||
conf_path = os.path.dirname(os.path.realpath(__file__)) + '/zabbix.ini'
|
||||
if os.path.exists(conf_path):
|
||||
config.read(conf_path)
|
||||
# server
|
||||
if config.has_option('zabbix', 'server'):
|
||||
self.zabbix_server = config.get('zabbix', 'server')
|
||||
|
||||
# login
|
||||
if config.has_option('zabbix', 'username'):
|
||||
self.zabbix_username = config.get('zabbix', 'username')
|
||||
if config.has_option('zabbix', 'password'):
|
||||
self.zabbix_password = config.get('zabbix', 'password')
|
||||
# ssl certs
|
||||
if config.has_option('zabbix', 'validate_certs'):
|
||||
if config.get('zabbix', 'validate_certs') in ['false', 'False', False]:
|
||||
self.validate_certs = False
|
||||
# host inventory
|
||||
if config.has_option('zabbix', 'read_host_inventory'):
|
||||
if config.get('zabbix', 'read_host_inventory') in ['true', 'True', True]:
|
||||
self.read_host_inventory = True
|
||||
# host interface
|
||||
if config.has_option('zabbix', 'use_host_interface'):
|
||||
if config.get('zabbix', 'use_host_interface') in ['false', 'False', False]:
|
||||
self.use_host_interface = False
|
||||
|
||||
def read_cli(self):
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--host')
|
||||
parser.add_argument('--list', action='store_true')
|
||||
self.options = parser.parse_args()
|
||||
|
||||
def hoststub(self):
|
||||
return {
|
||||
'hosts': []
|
||||
}
|
||||
|
||||
def get_host(self, api, name):
|
||||
api_query = {'output': 'extend', 'selectGroups': 'extend', "filter": {"host": [name]}}
|
||||
if self.use_host_interface:
|
||||
api_query['selectInterfaces'] = ['useip', 'ip', 'dns']
|
||||
if self.read_host_inventory:
|
||||
api_query['selectInventory'] = "extend"
|
||||
|
||||
data = {'ansible_ssh_host': name}
|
||||
if self.use_host_interface or self.read_host_inventory:
|
||||
try:
|
||||
hosts_data = api.host.get(api_query)[0]
|
||||
if 'interfaces' in hosts_data:
|
||||
# use first interface only
|
||||
if hosts_data['interfaces'][0]['useip'] == 0:
|
||||
data['ansible_ssh_host'] = hosts_data['interfaces'][0]['dns']
|
||||
else:
|
||||
data['ansible_ssh_host'] = hosts_data['interfaces'][0]['ip']
|
||||
if ('inventory' in hosts_data) and (hosts_data['inventory']):
|
||||
data.update(hosts_data['inventory'])
|
||||
except IndexError:
|
||||
# Host not found in zabbix
|
||||
pass
|
||||
return data
|
||||
|
||||
def get_list(self, api):
|
||||
api_query = {'output': 'extend', 'selectGroups': 'extend'}
|
||||
if self.use_host_interface:
|
||||
api_query['selectInterfaces'] = ['useip', 'ip', 'dns']
|
||||
if self.read_host_inventory:
|
||||
api_query['selectInventory'] = "extend"
|
||||
|
||||
hosts_data = api.host.get(api_query)
|
||||
data = {'_meta': {'hostvars': {}}}
|
||||
|
||||
data[self.defaultgroup] = self.hoststub()
|
||||
for host in hosts_data:
|
||||
hostname = host['name']
|
||||
hostvars = dict()
|
||||
data[self.defaultgroup]['hosts'].append(hostname)
|
||||
|
||||
for group in host['groups']:
|
||||
groupname = group['name']
|
||||
|
||||
if groupname not in data:
|
||||
data[groupname] = self.hoststub()
|
||||
|
||||
data[groupname]['hosts'].append(hostname)
|
||||
if 'interfaces' in host:
|
||||
# use first interface only
|
||||
if host['interfaces'][0]['useip'] == 0:
|
||||
hostvars['ansible_ssh_host'] = host['interfaces'][0]['dns']
|
||||
else:
|
||||
hostvars['ansible_ssh_host'] = host['interfaces'][0]['ip']
|
||||
if ('inventory' in host) and (host['inventory']):
|
||||
hostvars.update(host['inventory'])
|
||||
data['_meta']['hostvars'][hostname] = hostvars
|
||||
|
||||
return data
|
||||
|
||||
def __init__(self):
|
||||
|
||||
self.defaultgroup = 'group_all'
|
||||
self.zabbix_server = None
|
||||
self.zabbix_username = None
|
||||
self.zabbix_password = None
|
||||
self.validate_certs = True
|
||||
self.read_host_inventory = False
|
||||
self.use_host_interface = True
|
||||
|
||||
self.meta = {}
|
||||
|
||||
self.read_settings()
|
||||
self.read_cli()
|
||||
|
||||
if self.zabbix_server and self.zabbix_username:
|
||||
try:
|
||||
api = ZabbixAPI(server=self.zabbix_server, validate_certs=self.validate_certs)
|
||||
api.login(user=self.zabbix_username, password=self.zabbix_password)
|
||||
# zabbix_api tries to exit if it cannot parse what the zabbix server returned
|
||||
# so we have to use SystemExit here
|
||||
except (Exception, SystemExit) as e:
|
||||
print("Error: Could not login to Zabbix server. Check your zabbix.ini.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
if self.options.host:
|
||||
data = self.get_host(api, self.options.host)
|
||||
print(json.dumps(data, indent=2))
|
||||
|
||||
elif self.options.list:
|
||||
data = self.get_list(api)
|
||||
print(json.dumps(data, indent=2))
|
||||
|
||||
else:
|
||||
print("usage: --list ..OR.. --host <hostname>", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
else:
|
||||
print("Error: Configuration of server and credentials are required. See zabbix.ini.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
ZabbixInventory()
|
|
@ -1,5 +0,0 @@
|
|||
destructive
|
||||
shippable/posix/group1
|
||||
skip/osx
|
||||
skip/freebsd
|
||||
skip/rhel
|
|
@ -1,13 +0,0 @@
|
|||
---
|
||||
db_name: 'zabbix'
|
||||
db_user: 'zabbix'
|
||||
db_password: 'fLhijUs3PgekNhwJ'
|
||||
|
||||
zabbix_version: 4.4
|
||||
zabbix_apt_repository: 'deb http://repo.zabbix.com/zabbix/{{ zabbix_version }}/{{ ansible_distribution.lower() }}/ {{ ansible_distribution_release }} main'
|
||||
zabbix_apt_repository_key: 'http://repo.zabbix.com/zabbix-official-repo.key'
|
||||
|
||||
zabbix_packages:
|
||||
- zabbix-server-mysql
|
||||
- zabbix-frontend-php
|
||||
- zabbix-apache-conf
|
|
@ -1,15 +0,0 @@
|
|||
- name: remove zabbix repository
|
||||
apt_repository:
|
||||
repo: "{{ zabbix_apt_repository }}"
|
||||
filename: zabbix
|
||||
state: absent
|
||||
|
||||
- name: remove zabbix packages
|
||||
apt:
|
||||
name: "{{ zabbix_packages }}"
|
||||
state: absent
|
||||
|
||||
- name: remove zabbix pip packages
|
||||
pip:
|
||||
name: zabbix-api
|
||||
state: absent
|
|
@ -1,2 +0,0 @@
|
|||
dependencies:
|
||||
- setup_mysql_db
|
|
@ -1,3 +0,0 @@
|
|||
---
|
||||
- include: setup.yml
|
||||
when: ansible_os_family == 'Debian'
|
|
@ -1,75 +0,0 @@
|
|||
- name: install zabbix repository key
|
||||
apt_key:
|
||||
url: '{{ zabbix_apt_repository_key }}'
|
||||
state: present
|
||||
- name: install zabbix repository
|
||||
apt_repository:
|
||||
repo: '{{ zabbix_apt_repository }}'
|
||||
filename: zabbix
|
||||
state: present
|
||||
notify: remove zabbix repository
|
||||
- name: check if dpkg is set to exclude specific destinations
|
||||
stat:
|
||||
path: /etc/dpkg/dpkg.cfg.d/excludes
|
||||
register: dpkg_excludes
|
||||
- name: ensure documentation installations are allowed for zabbix
|
||||
lineinfile:
|
||||
path: /etc/dpkg/dpkg.cfg.d/excludes
|
||||
regexp: ^path-include=/usr/share/doc/zabbix*$
|
||||
line: path-include=/usr/share/doc/zabbix*
|
||||
state: present
|
||||
when: dpkg_excludes.stat.exists
|
||||
- name: install zabbix apt dependencies
|
||||
apt:
|
||||
name: '{{ zabbix_packages }}'
|
||||
state: latest
|
||||
update_cache: true
|
||||
notify: remove zabbix packages
|
||||
- name: install zabbix-api python package
|
||||
pip:
|
||||
name: zabbix-api
|
||||
state: latest
|
||||
notify: remove zabbix pip packages
|
||||
- name: create mysql user {{ db_user }}
|
||||
mysql_user:
|
||||
name: '{{ db_user }}'
|
||||
password: '{{ db_password }}'
|
||||
state: present
|
||||
priv: '{{ db_name }}.*:ALL'
|
||||
login_unix_socket: '{{ mysql_socket }}'
|
||||
- name: import initial zabbix database
|
||||
mysql_db:
|
||||
name: '{{ db_name }}'
|
||||
login_user: '{{ db_user }}'
|
||||
login_password: '{{ db_password }}'
|
||||
state: import
|
||||
target: /usr/share/doc/zabbix-server-mysql/create.sql.gz
|
||||
- name: deploy zabbix-server configuration
|
||||
template:
|
||||
src: zabbix_server.conf.j2
|
||||
dest: /etc/zabbix/zabbix_server.conf
|
||||
owner: root
|
||||
group: zabbix
|
||||
mode: '0640'
|
||||
- name: deploy zabbix web frontend configuration
|
||||
template:
|
||||
src: zabbix.conf.php.j2
|
||||
dest: /etc/zabbix/web/zabbix.conf.php
|
||||
mode: '0644'
|
||||
- name: Create proper run directory for zabbix-server
|
||||
file:
|
||||
path: /var/run/zabbix
|
||||
state: directory
|
||||
owner: zabbix
|
||||
group: zabbix
|
||||
mode: '0775'
|
||||
- name: restart zabbix-server
|
||||
service:
|
||||
name: zabbix-server
|
||||
state: restarted
|
||||
enabled: true
|
||||
- name: restart apache2
|
||||
service:
|
||||
name: apache2
|
||||
state: restarted
|
||||
enabled: true
|
|
@ -1,20 +0,0 @@
|
|||
<?php
|
||||
// Zabbix GUI configuration file
|
||||
global $DB;
|
||||
|
||||
$DB['TYPE'] = 'MYSQL';
|
||||
$DB['SERVER'] = 'localhost';
|
||||
$DB['PORT'] = '0';
|
||||
$DB['DATABASE'] = '{{ db_name }}';
|
||||
$DB['USER'] = '{{ db_user }}';
|
||||
$DB['PASSWORD'] = '{{ db_password }}';
|
||||
|
||||
// SCHEMA is relevant only for IBM_DB2 database
|
||||
$DB['SCHEMA'] = '';
|
||||
|
||||
$ZBX_SERVER = 'localhost';
|
||||
$ZBX_SERVER_PORT = '10051';
|
||||
$ZBX_SERVER_NAME = '';
|
||||
|
||||
$IMAGE_FORMAT_DEFAULT = IMAGE_FORMAT_PNG;
|
||||
?>
|
|
@ -1,7 +0,0 @@
|
|||
PidFile=/var/run/zabbix/zabbix_server.pid
|
||||
LogFile=/tmp/zabbix_server.log
|
||||
DBName={{ db_name }}
|
||||
DBUser={{ db_user }}
|
||||
DBPassword={{ db_password }}
|
||||
Timeout=4
|
||||
LogSlowQueries=3000
|
|
@ -1,6 +0,0 @@
|
|||
destructive
|
||||
shippable/posix/group1
|
||||
skip/aix
|
||||
skip/osx
|
||||
skip/freebsd
|
||||
skip/rhel
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
|
||||
zabbix_server_url: http://127.0.0.1/zabbix/
|
||||
zabbix_login_user: Admin
|
||||
zabbix_login_password: zabbix
|
|
@ -1,2 +0,0 @@
|
|||
dependencies:
|
||||
- setup_zabbix
|
|
@ -1,16 +0,0 @@
|
|||
---
|
||||
# setup stuff not testing zabbix_host
|
||||
- block:
|
||||
- include: zabbix_host_setup.yml
|
||||
|
||||
# zabbix_host module tests
|
||||
- include: zabbix_host_tests.yml
|
||||
|
||||
# documentation example tests
|
||||
- include: zabbix_host_doc.yml
|
||||
|
||||
# tear down stuff set up earlier
|
||||
- include: zabbix_host_teardown.yml
|
||||
|
||||
when:
|
||||
- ansible_distribution == 'Ubuntu'
|
|
@ -1,83 +0,0 @@
|
|||
---
|
||||
# These two tests are close to documentation example
|
||||
|
||||
- name: Create a new host or update an existing host's info
|
||||
zabbix_host:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
host_name: ExampleHost1
|
||||
visible_name: ExampleName
|
||||
description: My ExampleHost Description
|
||||
host_groups:
|
||||
- Linux servers
|
||||
- Zabbix servers
|
||||
link_templates:
|
||||
- Template App IMAP Service
|
||||
- Template App NTP Service
|
||||
status: enabled
|
||||
state: present
|
||||
inventory_mode: manual
|
||||
inventory_zabbix:
|
||||
tag: test-tag
|
||||
alias: test-alias
|
||||
notes: "Special Informations: test-info"
|
||||
location: test-location
|
||||
site_rack: test-rack
|
||||
os: test-os
|
||||
hardware: test-hw
|
||||
ipmi_authtype: 2
|
||||
ipmi_privilege: 4
|
||||
ipmi_username: username
|
||||
ipmi_password: password
|
||||
interfaces:
|
||||
- type: 1
|
||||
main: 1
|
||||
useip: 1
|
||||
ip: 10.1.1.1
|
||||
dns: ""
|
||||
port: "10050"
|
||||
- type: 4
|
||||
main: 1
|
||||
useip: 1
|
||||
ip: 10.1.1.1
|
||||
dns: ""
|
||||
port: "12345"
|
||||
macros:
|
||||
- macro: '{$EXAMPLEMACRO}'
|
||||
value: ExampleMacroValue
|
||||
- macro: EXAMPLEMACRO2
|
||||
value: ExampleMacroValue2
|
||||
description: Example desc that work only with Zabbix 4.4 and higher
|
||||
tags:
|
||||
- tag: ExampleHostsTag
|
||||
- tag: ExampleHostsTag2
|
||||
value: ExampleTagValue
|
||||
register: zabbix_host1
|
||||
|
||||
- name: Update an existing host's tls settings
|
||||
zabbix_host:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
host_name: ExampleHost2
|
||||
visible_name: ExampleName2
|
||||
interfaces:
|
||||
- type: 1
|
||||
main: 1
|
||||
useip: 1
|
||||
ip: 10.1.1.2
|
||||
dns: ""
|
||||
port: "10050"
|
||||
host_groups:
|
||||
- Linux servers
|
||||
tls_psk_identity: test
|
||||
tls_connect: 2
|
||||
tls_psk: 123456789abcdef123456789abcdef12
|
||||
register: zabbix_host2
|
||||
|
||||
- name: expect both to succeed
|
||||
assert:
|
||||
that:
|
||||
- "zabbix_host1 is changed"
|
||||
- "zabbix_host2 is changed"
|
|
@ -1,20 +0,0 @@
|
|||
---
|
||||
# set up a zabbix proxy to test zabbix_host with
|
||||
|
||||
- name: Create a new proxy
|
||||
zabbix_proxy:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
proxy_name: ExampleProxy
|
||||
description: ExampleProxy
|
||||
status: active
|
||||
state: present
|
||||
interface:
|
||||
type: 0
|
||||
main: 1
|
||||
useip: 1
|
||||
ip: 10.5.6.7
|
||||
dns: ""
|
||||
port: 10050
|
||||
register: zabbix_proxy
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
# remove zabbix_proxy (hopefully) created earlier
|
||||
|
||||
- name: remove proxy
|
||||
zabbix_proxy:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
proxy_name: ExampleProxy
|
||||
state: absent
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +0,0 @@
|
|||
destructive
|
||||
shippable/posix/group1
|
||||
skip/aix
|
||||
skip/osx
|
||||
skip/freebsd
|
||||
skip/rhel
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
|
||||
zabbix_server_url: http://127.0.0.1/zabbix/
|
||||
zabbix_login_user: Admin
|
||||
zabbix_login_password: zabbix
|
|
@ -1,2 +0,0 @@
|
|||
dependencies:
|
||||
- setup_zabbix
|
|
@ -1,159 +0,0 @@
|
|||
---
|
||||
- when:
|
||||
- ansible_distribution == 'Ubuntu'
|
||||
block:
|
||||
- name: Create a new Zabbix template.
|
||||
zabbix_template:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
template_name: ExampleHost
|
||||
template_groups:
|
||||
- 'Linux servers'
|
||||
- 'Templates'
|
||||
state: present
|
||||
register: create_zabbix_template_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- create_zabbix_template_result.changed is sameas true
|
||||
|
||||
- name: Gather Zabbix template infomation.
|
||||
zabbix_template_info:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
template_name: ExampleHost
|
||||
format: json
|
||||
register: gather_template_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- gather_template_result.template_json.zabbix_export.groups.0.name == 'Linux servers'
|
||||
- gather_template_result.template_json.zabbix_export.groups.1.name == 'Templates'
|
||||
|
||||
- name: Add link_templates to Zabbix template.
|
||||
zabbix_template:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
template_name: ExampleHost
|
||||
template_groups:
|
||||
- 'Linux servers'
|
||||
- 'Templates'
|
||||
link_templates:
|
||||
- 'Template App Zabbix Proxy'
|
||||
- 'Template Module Zabbix agent'
|
||||
state: present
|
||||
register: update_zabbix_template_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- create_zabbix_template_result.changed is sameas true
|
||||
|
||||
- name: Gather Zabbix template infomation.
|
||||
zabbix_template_info:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
template_name: ExampleHost
|
||||
format: json
|
||||
register: gather_template_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- gather_template_result.template_json.zabbix_export.groups.0.name == 'Linux servers'
|
||||
- gather_template_result.template_json.zabbix_export.groups.1.name == 'Templates'
|
||||
- gather_template_result.template_json.zabbix_export.templates.0.templates.0.name == 'Template App Zabbix Proxy'
|
||||
- gather_template_result.template_json.zabbix_export.templates.0.templates.1.name == 'Template Module Zabbix agent'
|
||||
|
||||
- name: Add macros to Zabbix template.
|
||||
zabbix_template:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
template_name: ExampleHost
|
||||
template_groups:
|
||||
- 'Linux servers'
|
||||
- 'Templates'
|
||||
link_templates:
|
||||
- 'Template App Zabbix Proxy'
|
||||
- 'Template Module Zabbix agent'
|
||||
macros:
|
||||
- macro: '{$EXAMPLE_MACRO1}'
|
||||
value: 1000
|
||||
- macro: '{$EXAMPLE_MACRO2}'
|
||||
value: 'text'
|
||||
state: present
|
||||
register: update_zabbix_template_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- create_zabbix_template_result.changed is sameas true
|
||||
|
||||
- name: Gather Zabbix template infomation.
|
||||
zabbix_template_info:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
template_name: ExampleHost
|
||||
format: json
|
||||
register: gather_template_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- gather_template_result.template_json.zabbix_export.groups.0.name == 'Linux servers'
|
||||
- gather_template_result.template_json.zabbix_export.groups.1.name == 'Templates'
|
||||
- gather_template_result.template_json.zabbix_export.templates.0.templates.0.name == 'Template App Zabbix Proxy'
|
||||
- gather_template_result.template_json.zabbix_export.templates.0.templates.1.name == 'Template Module Zabbix agent'
|
||||
- gather_template_result.template_json.zabbix_export.templates.0.macros.0.macro == '{$EXAMPLE_MACRO1}'
|
||||
- gather_template_result.template_json.zabbix_export.templates.0.macros.0.value == '1000'
|
||||
- gather_template_result.template_json.zabbix_export.templates.0.macros.1.macro == '{$EXAMPLE_MACRO2}'
|
||||
- gather_template_result.template_json.zabbix_export.templates.0.macros.1.value == 'text'
|
||||
|
||||
- name: Dump Zabbix template to XML format.
|
||||
zabbix_template:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
template_name: ExampleHost
|
||||
dump_format: xml
|
||||
state: dump
|
||||
register: template_dump_result
|
||||
|
||||
- debug: var=template_dump_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- template_dump_result.deprecations is defined
|
||||
- template_dump_result.deprecations.0.version == '2.14'
|
||||
|
||||
- name: Dump Zabbix template to JSON format.
|
||||
zabbix_template:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
template_name: ExampleHost
|
||||
dump_format: json
|
||||
state: dump
|
||||
register: template_dump_result
|
||||
|
||||
- debug: var=template_dump_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- template_dump_result.deprecations is defined
|
||||
- template_dump_result.deprecations.0.version == '2.14'
|
||||
|
||||
- name: Delete Zabbix template.
|
||||
zabbix_template:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
template_name: ExampleHost
|
||||
state: absent
|
||||
register: delete_zabbix_template_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- delete_zabbix_template_result.changed is sameas true
|
|
@ -1,6 +0,0 @@
|
|||
destructive
|
||||
shippable/posix/group1
|
||||
skip/osx
|
||||
skip/freebsd
|
||||
skip/rhel
|
||||
skip/aix
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
|
||||
zabbix_server_url: http://127.0.0.1/zabbix/
|
||||
zabbix_login_user: Admin
|
||||
zabbix_login_password: zabbix
|
|
@ -1,2 +0,0 @@
|
|||
dependencies:
|
||||
- setup_zabbix
|
|
@ -1,912 +0,0 @@
|
|||
---
|
||||
- when:
|
||||
- ansible_distribution == 'Ubuntu'
|
||||
block:
|
||||
# New user create test from here
|
||||
- name: test - Create a new Zabbix user with check_mode and diff
|
||||
zabbix_user:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
alias: example1
|
||||
name: example
|
||||
surname: test
|
||||
usrgrps:
|
||||
- Guests
|
||||
passwd: password
|
||||
check_mode: yes
|
||||
diff: yes
|
||||
register: create_zabbix_user_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- create_zabbix_user_result.changed is sameas true
|
||||
|
||||
- name: test - Create a new Zabbix user
|
||||
zabbix_user:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
alias: example1
|
||||
name: example
|
||||
surname: test
|
||||
usrgrps:
|
||||
- Guests
|
||||
passwd: password
|
||||
register: create_zabbix_user_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- create_zabbix_user_result.changed is sameas true
|
||||
|
||||
- name: test - Create a new Zabbix user(again)
|
||||
zabbix_user:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
alias: example1
|
||||
name: example
|
||||
surname: test
|
||||
usrgrps:
|
||||
- Guests
|
||||
passwd: password
|
||||
register: create_zabbix_user_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- not create_zabbix_user_result.changed is sameas true
|
||||
|
||||
# Parameter add test from here to existing user
|
||||
- name: test - Add user group to existing user
|
||||
zabbix_user:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
alias: example1
|
||||
name: example
|
||||
surname: test
|
||||
usrgrps:
|
||||
- Guests
|
||||
- Zabbix administrators
|
||||
passwd: password
|
||||
register: add_usergroup_to_existing_user_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- add_usergroup_to_existing_user_result.changed is sameas true
|
||||
|
||||
- name: test - Add user medias(Email) to existing user
|
||||
zabbix_user:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
alias: example1
|
||||
name: example
|
||||
surname: test
|
||||
usrgrps:
|
||||
- Guests
|
||||
- Zabbix administrators
|
||||
passwd: password
|
||||
user_medias:
|
||||
- mediatype: Email
|
||||
sendto: example@example.com
|
||||
period: 1-7,00:00-24:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: yes
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
register: add_user_medias_to_existing_user_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- add_user_medias_to_existing_user_result.changed is sameas true
|
||||
|
||||
- name: test - Add multiple user medias(Email and SMS) to existing user
|
||||
zabbix_user:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
alias: example1
|
||||
name: example
|
||||
surname: test
|
||||
usrgrps:
|
||||
- Guests
|
||||
- Zabbix administrators
|
||||
passwd: password
|
||||
user_medias:
|
||||
- mediatype: Email
|
||||
sendto: example@example.com
|
||||
period: 1-7,00:00-24:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: yes
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
- mediatype: SMS
|
||||
sendto: example@example.com
|
||||
period: 1-5,01:00-23:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: no
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
register: add_user_medias_to_existing_user_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- add_user_medias_to_existing_user_result.changed is sameas true
|
||||
|
||||
# Existing parameter updates test from here
|
||||
- name: test - Update password parameter for existing user
|
||||
zabbix_user:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
alias: example1
|
||||
name: example
|
||||
surname: test
|
||||
usrgrps:
|
||||
- Guests
|
||||
- Zabbix administrators
|
||||
passwd: update_password
|
||||
override_passwd: yes
|
||||
user_medias:
|
||||
- mediatype: Email
|
||||
sendto: example@example.com
|
||||
period: 1-7,00:00-24:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: yes
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
- mediatype: SMS
|
||||
sendto: example@example.com
|
||||
period: 1-5,01:00-23:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: no
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
register: update_password_parameter_existing_user_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- update_password_parameter_existing_user_result.changed is sameas true
|
||||
|
||||
- name: test - Update autologin parameter for existing user
|
||||
zabbix_user:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
alias: example1
|
||||
name: example
|
||||
surname: test
|
||||
usrgrps:
|
||||
- Guests
|
||||
- Zabbix administrators
|
||||
passwd: update_password
|
||||
autologin: yes
|
||||
user_medias:
|
||||
- mediatype: Email
|
||||
sendto: example@example.com
|
||||
period: 1-7,00:00-24:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: yes
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
- mediatype: SMS
|
||||
sendto: example@example.com
|
||||
period: 1-5,01:00-23:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: no
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
register: update_autologin_parameter_existing_user_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- update_autologin_parameter_existing_user_result.changed is sameas true
|
||||
|
||||
- name: test - Update autologout parameter for existing user
|
||||
zabbix_user:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
alias: example1
|
||||
name: example
|
||||
surname: test
|
||||
usrgrps:
|
||||
- Guests
|
||||
- Zabbix administrators
|
||||
passwd: update_password
|
||||
autologout: 500
|
||||
user_medias:
|
||||
- mediatype: Email
|
||||
sendto: example@example.com
|
||||
period: 1-7,00:00-24:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: yes
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
- mediatype: SMS
|
||||
sendto: example@example.com
|
||||
period: 1-5,01:00-23:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: no
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
register: update_autologout_parameter_existing_user_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- update_autologout_parameter_existing_user_result.changed is sameas true
|
||||
|
||||
- name: test - Update refresh parameter for existing user
|
||||
zabbix_user:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
alias: example1
|
||||
name: example
|
||||
surname: test
|
||||
usrgrps:
|
||||
- Guests
|
||||
- Zabbix administrators
|
||||
passwd: update_password
|
||||
autologout: 500
|
||||
refresh: 60
|
||||
user_medias:
|
||||
- mediatype: Email
|
||||
sendto: example@example.com
|
||||
period: 1-7,00:00-24:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: yes
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
- mediatype: SMS
|
||||
sendto: example@example.com
|
||||
period: 1-5,01:00-23:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: no
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
register: update_refresh_parameter_existing_user_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- update_refresh_parameter_existing_user_result.changed is sameas true
|
||||
|
||||
- name: test - Update rows_per_page parameter for existing user
|
||||
zabbix_user:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
alias: example1
|
||||
name: example
|
||||
surname: test
|
||||
usrgrps:
|
||||
- Guests
|
||||
- Zabbix administrators
|
||||
passwd: update_password
|
||||
autologout: 500
|
||||
refresh: 60
|
||||
rows_per_page: 300
|
||||
user_medias:
|
||||
- mediatype: Email
|
||||
sendto: example@example.com
|
||||
period: 1-7,00:00-24:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: yes
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
- mediatype: SMS
|
||||
sendto: example@example.com
|
||||
period: 1-5,01:00-23:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: no
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
register: update_rows_per_page_parameter_existing_user_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- update_rows_per_page_parameter_existing_user_result.changed is sameas true
|
||||
|
||||
- name: test - Update after_login_url parameter for existing user
|
||||
zabbix_user:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
alias: example1
|
||||
name: example
|
||||
surname: test
|
||||
usrgrps:
|
||||
- Guests
|
||||
- Zabbix administrators
|
||||
passwd: update_password
|
||||
autologout: 500
|
||||
refresh: 60
|
||||
rows_per_page: 300
|
||||
after_login_url: http://example.com
|
||||
user_medias:
|
||||
- mediatype: Email
|
||||
sendto: example@example.com
|
||||
period: 1-7,00:00-24:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: yes
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
- mediatype: SMS
|
||||
sendto: example@example.com
|
||||
period: 1-5,01:00-23:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: no
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
register: update_after_login_url_parameter_existing_user_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- update_after_login_url_parameter_existing_user_result.changed is sameas true
|
||||
|
||||
- name: test - Update theme parameter for existing user
|
||||
zabbix_user:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
alias: example1
|
||||
name: example
|
||||
surname: test
|
||||
usrgrps:
|
||||
- Guests
|
||||
- Zabbix administrators
|
||||
passwd: update_password
|
||||
autologout: 500
|
||||
refresh: 60
|
||||
rows_per_page: 300
|
||||
after_login_url: http://example.com
|
||||
theme: "{{ item }}"
|
||||
user_medias:
|
||||
- mediatype: Email
|
||||
sendto: example@example.com
|
||||
period: 1-7,00:00-24:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: yes
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
- mediatype: SMS
|
||||
sendto: example@example.com
|
||||
period: 1-5,01:00-23:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: no
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
loop:
|
||||
- blue-theme
|
||||
- dark-theme
|
||||
register: update_theme_parameter_existing_user_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- item.changed is sameas true
|
||||
loop: "{{ update_theme_parameter_existing_user_result.results }}"
|
||||
|
||||
- name: test - Update type parameter for existing user
|
||||
zabbix_user:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
alias: example1
|
||||
name: example
|
||||
surname: test
|
||||
usrgrps:
|
||||
- Guests
|
||||
- Zabbix administrators
|
||||
passwd: update_password
|
||||
autologout: 500
|
||||
refresh: 60
|
||||
rows_per_page: 300
|
||||
after_login_url: http://example.com
|
||||
theme: dark-theme
|
||||
type: "{{ item }}"
|
||||
user_medias:
|
||||
- mediatype: Email
|
||||
sendto: example@example.com
|
||||
period: 1-7,00:00-24:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: yes
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
- mediatype: SMS
|
||||
sendto: example@example.com
|
||||
period: 1-5,01:00-23:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: no
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
loop:
|
||||
- Zabbix admin
|
||||
- Zabbix super admin
|
||||
register: update_type_parameter_existing_user_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- item.changed is sameas true
|
||||
loop: "{{ update_type_parameter_existing_user_result.results }}"
|
||||
|
||||
- name: test - Update lang parameter for existing user
|
||||
zabbix_user:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
alias: example1
|
||||
name: example
|
||||
surname: test
|
||||
usrgrps:
|
||||
- Guests
|
||||
- Zabbix administrators
|
||||
passwd: update_password
|
||||
autologout: 500
|
||||
refresh: 60
|
||||
rows_per_page: 300
|
||||
after_login_url: http://example.com
|
||||
theme: dark-theme
|
||||
type: Zabbix super admin
|
||||
lang: en_US
|
||||
user_medias:
|
||||
- mediatype: Email
|
||||
sendto: example@example.com
|
||||
period: 1-7,00:00-24:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: yes
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
- mediatype: SMS
|
||||
sendto: example@example.com
|
||||
period: 1-5,01:00-23:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: no
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
register: update_lang_parameter_existing_user_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- update_lang_parameter_existing_user_result.changed is sameas true
|
||||
|
||||
- name: test - Update name and surname parameter for existing user
|
||||
zabbix_user:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
alias: example1
|
||||
name: example2
|
||||
surname: test2
|
||||
usrgrps:
|
||||
- Guests
|
||||
- Zabbix administrators
|
||||
passwd: update_password
|
||||
autologout: 500
|
||||
refresh: 60
|
||||
rows_per_page: 300
|
||||
after_login_url: http://example.com
|
||||
theme: dark-theme
|
||||
type: Zabbix super admin
|
||||
lang: en_US
|
||||
user_medias:
|
||||
- mediatype: Email
|
||||
sendto: example@example.com
|
||||
period: 1-7,00:00-24:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: yes
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
- mediatype: SMS
|
||||
sendto: example@example.com
|
||||
period: 1-5,01:00-23:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: no
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
register: update_name_and_surname_parameter_existing_user_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- update_name_and_surname_parameter_existing_user_result.changed is sameas true
|
||||
|
||||
- name: test - Update lang parameter for existing user with check_mode and diff
|
||||
zabbix_user:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
alias: example1
|
||||
name: example2
|
||||
surname: test2
|
||||
usrgrps:
|
||||
- Guests
|
||||
- Zabbix administrators
|
||||
passwd: update_password
|
||||
autologout: 500
|
||||
refresh: 60
|
||||
rows_per_page: 300
|
||||
after_login_url: http://example.com
|
||||
theme: dark-theme
|
||||
type: Zabbix super admin
|
||||
lang: en_GB
|
||||
user_medias:
|
||||
- mediatype: Email
|
||||
sendto: example@example.com
|
||||
period: 1-7,00:00-24:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: yes
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
- mediatype: SMS
|
||||
sendto: example@example.com
|
||||
period: 1-5,01:00-23:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: no
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
check_mode: yes
|
||||
diff: yes
|
||||
register: update_lang_parameter_existing_user_with_check_mode_diff_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- update_lang_parameter_existing_user_with_check_mode_diff_result.changed is sameas true
|
||||
|
||||
- name: test - Update lang parameter for existing user
|
||||
zabbix_user:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
alias: example1
|
||||
name: example2
|
||||
surname: test2
|
||||
usrgrps:
|
||||
- Guests
|
||||
- Zabbix administrators
|
||||
passwd: update_password
|
||||
autologout: 500
|
||||
refresh: 60
|
||||
rows_per_page: 300
|
||||
after_login_url: http://example.com
|
||||
theme: dark-theme
|
||||
type: Zabbix super admin
|
||||
lang: en_GB
|
||||
user_medias:
|
||||
- mediatype: Email
|
||||
sendto: example@example.com
|
||||
period: 1-7,00:00-24:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: yes
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
- mediatype: SMS
|
||||
sendto: example@example.com
|
||||
period: 1-5,01:00-23:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: no
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
register: update_lang_parameter_existing_user_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- update_lang_parameter_existing_user_result.changed is sameas true
|
||||
|
||||
- name: test - Update lang parameter for existing user(again)
|
||||
zabbix_user:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
alias: example1
|
||||
name: example2
|
||||
surname: test2
|
||||
usrgrps:
|
||||
- Guests
|
||||
- Zabbix administrators
|
||||
passwd: update_password
|
||||
autologout: 500
|
||||
refresh: 60
|
||||
rows_per_page: 300
|
||||
after_login_url: http://example.com
|
||||
theme: dark-theme
|
||||
type: Zabbix super admin
|
||||
lang: en_GB
|
||||
user_medias:
|
||||
- mediatype: Email
|
||||
sendto: example@example.com
|
||||
period: 1-7,00:00-24:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: yes
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
- mediatype: SMS
|
||||
sendto: example@example.com
|
||||
period: 1-5,01:00-23:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: no
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
register: update_lang_parameter_existing_user_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- not update_lang_parameter_existing_user_result.changed is sameas true
|
||||
|
||||
# Parameter delete test from here from existing user
|
||||
- name: test - Delete user medias(SNS) for existing user with check_mode and diff
|
||||
zabbix_user:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
alias: example1
|
||||
name: example2
|
||||
surname: test2
|
||||
usrgrps:
|
||||
- Guests
|
||||
- Zabbix administrators
|
||||
passwd: update_password
|
||||
autologout: 500
|
||||
refresh: 60
|
||||
rows_per_page: 300
|
||||
after_login_url: http://example.com
|
||||
theme: dark-theme
|
||||
type: Zabbix super admin
|
||||
lang: en_GB
|
||||
user_medias:
|
||||
- mediatype: Email
|
||||
sendto: example@example.com
|
||||
period: 1-7,00:00-24:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: yes
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
check_mode: yes
|
||||
diff: yes
|
||||
register: delete_user_medias_existing_user_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- delete_user_medias_existing_user_result.changed is sameas true
|
||||
|
||||
- name: test - Delete user medias(SNS) for existing user
|
||||
zabbix_user:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
alias: example1
|
||||
name: example2
|
||||
surname: test2
|
||||
usrgrps:
|
||||
- Guests
|
||||
- Zabbix administrators
|
||||
passwd: update_password
|
||||
autologout: 500
|
||||
refresh: 60
|
||||
rows_per_page: 300
|
||||
after_login_url: http://example.com
|
||||
theme: dark-theme
|
||||
type: Zabbix super admin
|
||||
lang: en_GB
|
||||
user_medias:
|
||||
- mediatype: Email
|
||||
sendto: example@example.com
|
||||
period: 1-7,00:00-24:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: yes
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
register: delete_user_medias_existing_user_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- delete_user_medias_existing_user_result.changed is sameas true
|
||||
|
||||
- name: test - Delete user group for existing user
|
||||
zabbix_user:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
alias: example1
|
||||
name: example2
|
||||
surname: test2
|
||||
usrgrps:
|
||||
- Zabbix administrators
|
||||
passwd: update_password
|
||||
autologout: 500
|
||||
refresh: 60
|
||||
rows_per_page: 300
|
||||
after_login_url: http://example.com
|
||||
theme: dark-theme
|
||||
type: Zabbix super admin
|
||||
lang: en_GB
|
||||
user_medias:
|
||||
- mediatype: Email
|
||||
sendto: example@example.com
|
||||
period: 1-7,00:00-24:00
|
||||
severity:
|
||||
not_classified: no
|
||||
information: yes
|
||||
warning: yes
|
||||
average: yes
|
||||
high: yes
|
||||
disaster: yes
|
||||
active: yes
|
||||
register: delete_user_group_existing_user_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- delete_user_group_existing_user_result.changed is sameas true
|
||||
|
||||
- name: test - Delete existing user with check_mode and diff
|
||||
zabbix_user:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
alias: example1
|
||||
usrgrps:
|
||||
- Zabbix administrators
|
||||
passwd: update_password
|
||||
state: absent
|
||||
check_mode: yes
|
||||
diff: yes
|
||||
register: delete_existing_user_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- delete_existing_user_result.changed is sameas true
|
||||
|
||||
- name: test - Delete existing user
|
||||
zabbix_user:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
alias: example1
|
||||
usrgrps:
|
||||
- Zabbix administrators
|
||||
passwd: update_password
|
||||
state: absent
|
||||
register: delete_existing_user_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- delete_existing_user_result.changed is sameas true
|
||||
|
||||
- name: test - Delete existing user(again)
|
||||
zabbix_user:
|
||||
server_url: "{{ zabbix_server_url }}"
|
||||
login_user: "{{ zabbix_login_user }}"
|
||||
login_password: "{{ zabbix_login_password }}"
|
||||
alias: example1
|
||||
usrgrps:
|
||||
- Zabbix administrators
|
||||
passwd: update_password
|
||||
state: absent
|
||||
register: delete_existing_user_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- not delete_existing_user_result.changed is sameas true
|
|
@ -85,8 +85,6 @@ scripts/inventory/vagrant.py future-import-boilerplate
|
|||
scripts/inventory/vagrant.py metaclass-boilerplate
|
||||
scripts/inventory/vbox.py future-import-boilerplate
|
||||
scripts/inventory/vbox.py metaclass-boilerplate
|
||||
scripts/inventory/zabbix.py future-import-boilerplate
|
||||
scripts/inventory/zabbix.py metaclass-boilerplate
|
||||
scripts/inventory/zone.py future-import-boilerplate
|
||||
scripts/inventory/zone.py metaclass-boilerplate
|
||||
scripts/vault/azure_vault.py future-import-boilerplate
|
||||
|
@ -1106,32 +1104,6 @@ plugins/modules/monitoring/statusio_maintenance.py validate-modules:doc-missing-
|
|||
plugins/modules/monitoring/statusio_maintenance.py validate-modules:parameter-list-no-elements
|
||||
plugins/modules/monitoring/statusio_maintenance.py validate-modules:parameter-type-not-in-doc
|
||||
plugins/modules/monitoring/uptimerobot.py validate-modules:doc-missing-type
|
||||
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:doc-choices-do-not-match-spec
|
||||
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:doc-default-does-not-match-spec
|
||||
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:doc-elements-mismatch
|
||||
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:doc-required-mismatch
|
||||
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:invalid-argument-name
|
||||
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:missing-suboption-docs
|
||||
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:nonexistent-parameter-documented
|
||||
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:parameter-list-no-elements
|
||||
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:parameter-type-not-in-doc
|
||||
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:undocumented-parameter
|
||||
plugins/modules/monitoring/zabbix/zabbix_group.py validate-modules:doc-elements-mismatch
|
||||
plugins/modules/monitoring/zabbix/zabbix_group.py validate-modules:parameter-list-no-elements
|
||||
plugins/modules/monitoring/zabbix/zabbix_group_info.py validate-modules:doc-elements-mismatch
|
||||
plugins/modules/monitoring/zabbix/zabbix_group_info.py validate-modules:parameter-list-no-elements
|
||||
plugins/modules/monitoring/zabbix/zabbix_host.py validate-modules:doc-elements-mismatch
|
||||
plugins/modules/monitoring/zabbix/zabbix_host.py validate-modules:parameter-list-no-elements
|
||||
plugins/modules/monitoring/zabbix/zabbix_host_info.py validate-modules:doc-elements-mismatch
|
||||
plugins/modules/monitoring/zabbix/zabbix_host_info.py validate-modules:parameter-list-no-elements
|
||||
plugins/modules/monitoring/zabbix/zabbix_maintenance.py validate-modules:doc-elements-mismatch
|
||||
plugins/modules/monitoring/zabbix/zabbix_maintenance.py validate-modules:parameter-list-no-elements
|
||||
plugins/modules/monitoring/zabbix/zabbix_mediatype.py validate-modules:doc-elements-mismatch
|
||||
plugins/modules/monitoring/zabbix/zabbix_mediatype.py validate-modules:parameter-list-no-elements
|
||||
plugins/modules/monitoring/zabbix/zabbix_template.py validate-modules:doc-elements-mismatch
|
||||
plugins/modules/monitoring/zabbix/zabbix_template.py validate-modules:parameter-list-no-elements
|
||||
plugins/modules/monitoring/zabbix/zabbix_user.py validate-modules:doc-elements-mismatch
|
||||
plugins/modules/monitoring/zabbix/zabbix_user.py validate-modules:parameter-list-no-elements
|
||||
plugins/modules/net_tools/cloudflare_dns.py validate-modules:parameter-type-not-in-doc
|
||||
plugins/modules/net_tools/dnsimple.py validate-modules:parameter-list-no-elements
|
||||
plugins/modules/net_tools/dnsmadeeasy.py validate-modules:doc-missing-type
|
||||
|
@ -3543,8 +3515,6 @@ plugins/doc_fragments/vultr.py future-import-boilerplate
|
|||
plugins/doc_fragments/vultr.py metaclass-boilerplate
|
||||
plugins/doc_fragments/xenserver.py future-import-boilerplate
|
||||
plugins/doc_fragments/xenserver.py metaclass-boilerplate
|
||||
plugins/doc_fragments/zabbix.py future-import-boilerplate
|
||||
plugins/doc_fragments/zabbix.py metaclass-boilerplate
|
||||
tests/integration/targets/inventory_kubevirt/inventory_diff.py future-import-boilerplate
|
||||
tests/integration/targets/inventory_kubevirt/inventory_diff.py metaclass-boilerplate
|
||||
tests/integration/targets/inventory_kubevirt/server.py future-import-boilerplate
|
||||
|
@ -3814,4 +3784,4 @@ tests/unit/modules/web_infrastructure/test_apache2_module.py metaclass-boilerpla
|
|||
tests/unit/modules/web_infrastructure/test_jenkins_plugin.py future-import-boilerplate
|
||||
tests/unit/modules/web_infrastructure/test_jenkins_plugin.py metaclass-boilerplate
|
||||
tests/unit/plugins/httpapi/test_ftd.py future-import-boilerplate
|
||||
tests/unit/plugins/httpapi/test_ftd.py metaclass-boilerplate
|
||||
tests/unit/plugins/httpapi/test_ftd.py metaclass-boilerplate
|
||||
|
|
|
@ -85,8 +85,6 @@ scripts/inventory/vagrant.py future-import-boilerplate
|
|||
scripts/inventory/vagrant.py metaclass-boilerplate
|
||||
scripts/inventory/vbox.py future-import-boilerplate
|
||||
scripts/inventory/vbox.py metaclass-boilerplate
|
||||
scripts/inventory/zabbix.py future-import-boilerplate
|
||||
scripts/inventory/zabbix.py metaclass-boilerplate
|
||||
scripts/inventory/zone.py future-import-boilerplate
|
||||
scripts/inventory/zone.py metaclass-boilerplate
|
||||
scripts/vault/azure_vault.py future-import-boilerplate
|
||||
|
@ -1106,32 +1104,6 @@ plugins/modules/monitoring/statusio_maintenance.py validate-modules:doc-missing-
|
|||
plugins/modules/monitoring/statusio_maintenance.py validate-modules:parameter-list-no-elements
|
||||
plugins/modules/monitoring/statusio_maintenance.py validate-modules:parameter-type-not-in-doc
|
||||
plugins/modules/monitoring/uptimerobot.py validate-modules:doc-missing-type
|
||||
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:doc-choices-do-not-match-spec
|
||||
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:doc-default-does-not-match-spec
|
||||
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:doc-elements-mismatch
|
||||
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:doc-required-mismatch
|
||||
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:invalid-argument-name
|
||||
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:missing-suboption-docs
|
||||
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:nonexistent-parameter-documented
|
||||
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:parameter-list-no-elements
|
||||
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:parameter-type-not-in-doc
|
||||
plugins/modules/monitoring/zabbix/zabbix_action.py validate-modules:undocumented-parameter
|
||||
plugins/modules/monitoring/zabbix/zabbix_group.py validate-modules:doc-elements-mismatch
|
||||
plugins/modules/monitoring/zabbix/zabbix_group.py validate-modules:parameter-list-no-elements
|
||||
plugins/modules/monitoring/zabbix/zabbix_group_info.py validate-modules:doc-elements-mismatch
|
||||
plugins/modules/monitoring/zabbix/zabbix_group_info.py validate-modules:parameter-list-no-elements
|
||||
plugins/modules/monitoring/zabbix/zabbix_host.py validate-modules:doc-elements-mismatch
|
||||
plugins/modules/monitoring/zabbix/zabbix_host.py validate-modules:parameter-list-no-elements
|
||||
plugins/modules/monitoring/zabbix/zabbix_host_info.py validate-modules:doc-elements-mismatch
|
||||
plugins/modules/monitoring/zabbix/zabbix_host_info.py validate-modules:parameter-list-no-elements
|
||||
plugins/modules/monitoring/zabbix/zabbix_maintenance.py validate-modules:doc-elements-mismatch
|
||||
plugins/modules/monitoring/zabbix/zabbix_maintenance.py validate-modules:parameter-list-no-elements
|
||||
plugins/modules/monitoring/zabbix/zabbix_mediatype.py validate-modules:doc-elements-mismatch
|
||||
plugins/modules/monitoring/zabbix/zabbix_mediatype.py validate-modules:parameter-list-no-elements
|
||||
plugins/modules/monitoring/zabbix/zabbix_template.py validate-modules:doc-elements-mismatch
|
||||
plugins/modules/monitoring/zabbix/zabbix_template.py validate-modules:parameter-list-no-elements
|
||||
plugins/modules/monitoring/zabbix/zabbix_user.py validate-modules:doc-elements-mismatch
|
||||
plugins/modules/monitoring/zabbix/zabbix_user.py validate-modules:parameter-list-no-elements
|
||||
plugins/modules/net_tools/cloudflare_dns.py validate-modules:parameter-type-not-in-doc
|
||||
plugins/modules/net_tools/dnsimple.py validate-modules:parameter-list-no-elements
|
||||
plugins/modules/net_tools/dnsmadeeasy.py validate-modules:doc-missing-type
|
||||
|
@ -3543,8 +3515,6 @@ plugins/doc_fragments/vultr.py future-import-boilerplate
|
|||
plugins/doc_fragments/vultr.py metaclass-boilerplate
|
||||
plugins/doc_fragments/xenserver.py future-import-boilerplate
|
||||
plugins/doc_fragments/xenserver.py metaclass-boilerplate
|
||||
plugins/doc_fragments/zabbix.py future-import-boilerplate
|
||||
plugins/doc_fragments/zabbix.py metaclass-boilerplate
|
||||
tests/integration/targets/inventory_kubevirt/inventory_diff.py future-import-boilerplate
|
||||
tests/integration/targets/inventory_kubevirt/inventory_diff.py metaclass-boilerplate
|
||||
tests/integration/targets/inventory_kubevirt/server.py future-import-boilerplate
|
||||
|
@ -3814,4 +3784,4 @@ tests/unit/modules/web_infrastructure/test_apache2_module.py metaclass-boilerpla
|
|||
tests/unit/modules/web_infrastructure/test_jenkins_plugin.py future-import-boilerplate
|
||||
tests/unit/modules/web_infrastructure/test_jenkins_plugin.py metaclass-boilerplate
|
||||
tests/unit/plugins/httpapi/test_ftd.py future-import-boilerplate
|
||||
tests/unit/plugins/httpapi/test_ftd.py metaclass-boilerplate
|
||||
tests/unit/plugins/httpapi/test_ftd.py metaclass-boilerplate
|
||||
|
|
Loading…
Reference in a new issue