mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-04-26 20:31:27 -07:00
* Update zabbix_screen.py limit screen columns Add option graphs_in_row that allows to limit the count of columns on zabbix screen. When graphs_in_row columns is filled, begins to draw next row. If there is many hosts with many graphs each, draws all graphs for one host in an column each below each other * fix remove whitespaces before and after brackets Fixing ansible-test sanity --test pep8 errors moved * fix documentation parsing error Fixing error: missing documentation (or could not parse documentation): expected string or buffer
420 lines
17 KiB
Python
420 lines
17 KiB
Python
#!/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 = '''
|
|
---
|
|
module: zabbix_screen
|
|
short_description: Zabbix screen creates/updates/deletes
|
|
description:
|
|
- This module allows you to create, modify and delete Zabbix screens and associated graph data.
|
|
version_added: "2.0"
|
|
author:
|
|
- "(@cove)"
|
|
- "Tony Minfei Ding"
|
|
- "Harrison Gu (@harrisongu)"
|
|
requirements:
|
|
- "python >= 2.6"
|
|
- zabbix-api
|
|
options:
|
|
screens:
|
|
description:
|
|
- List of screens to be created/updated/deleted(see example).
|
|
- If the screen(s) already been added, the screen(s) name won't be updated.
|
|
- When creating or updating screen(s), C(screen_name), C(host_group) are required.
|
|
- When deleting screen(s), the C(screen_name) is required.
|
|
- Option C(graphs_in_row) will limit columns of screen and make multiple rows (default 3)
|
|
- >
|
|
The available states are: C(present) (default) and C(absent). If the screen(s) already exists, and the state is not C(absent), the screen(s)
|
|
will just be updated as needed.
|
|
required: true
|
|
|
|
extends_documentation_fragment:
|
|
- zabbix
|
|
|
|
notes:
|
|
- Too many concurrent updates to the same screen may cause Zabbix to return errors, see examples for a workaround if needed.
|
|
'''
|
|
|
|
EXAMPLES = '''
|
|
# 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]
|
|
'''
|
|
|
|
try:
|
|
from zabbix_api import ZabbixAPI, ZabbixAPISubClass
|
|
from zabbix_api import ZabbixAPIException
|
|
from zabbix_api import Already_Exists
|
|
|
|
# Extend the ZabbixAPI
|
|
# Since the zabbix-api python module too old (version 1.0, and there's no higher version so far), it doesn't support the 'screenitem' api call,
|
|
# we have to inherit the ZabbixAPI class to add 'screenitem' support.
|
|
class ZabbixAPIExtends(ZabbixAPI):
|
|
screenitem = None
|
|
|
|
def __init__(self, server, timeout, user, passwd, validate_certs, **kwargs):
|
|
ZabbixAPI.__init__(self, server, timeout=timeout, user=user, passwd=passwd, validate_certs=validate_certs)
|
|
self.screenitem = ZabbixAPISubClass(self, dict({"prefix": "screenitem"}, **kwargs))
|
|
|
|
HAS_ZABBIX_API = True
|
|
except ImportError:
|
|
HAS_ZABBIX_API = False
|
|
|
|
from ansible.module_utils.basic import AnsibleModule
|
|
|
|
|
|
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):
|
|
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:
|
|
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', required=True)
|
|
),
|
|
supports_check_mode=True
|
|
)
|
|
|
|
if not HAS_ZABBIX_API:
|
|
module.fail_json(msg="Missing required zabbix-api module (check docs or install with: pip install zabbix-api)")
|
|
|
|
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 = ZabbixAPIExtends(server_url, timeout=timeout, user=http_login_user, passwd=http_login_password,
|
|
validate_certs=validate_certs)
|
|
zbx.login(login_user, login_password)
|
|
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 = "absent" if "state" in zabbix_screen and zabbix_screen['state'] == "absent" else "present"
|
|
|
|
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 = 3
|
|
if 'graphs_in_row' in zabbix_screen:
|
|
graphs_in_row = zabbix_screen['graphs_in_row']
|
|
graph_width = None
|
|
if 'graph_width' in zabbix_screen:
|
|
graph_width = zabbix_screen['graph_width']
|
|
graph_height = None
|
|
if 'graph_height' in zabbix_screen:
|
|
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)
|
|
|
|
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()
|