zbx_graph.py 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. #!/usr/bin/env python
  2. '''
  3. Ansible module for zabbix graphs
  4. '''
  5. # vim: expandtab:tabstop=4:shiftwidth=4
  6. #
  7. # Zabbix graphs ansible module
  8. #
  9. #
  10. # Copyright 2015 Red Hat Inc.
  11. #
  12. # Licensed under the Apache License, Version 2.0 (the "License");
  13. # you may not use this file except in compliance with the License.
  14. # You may obtain a copy of the License at
  15. #
  16. # http://www.apache.org/licenses/LICENSE-2.0
  17. #
  18. # Unless required by applicable law or agreed to in writing, software
  19. # distributed under the License is distributed on an "AS IS" BASIS,
  20. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  21. # See the License for the specific language governing permissions and
  22. # limitations under the License.
  23. #
  24. #---
  25. #- hosts: localhost
  26. # gather_facts: no
  27. # tasks:
  28. # - zbx_graph:
  29. # zbx_server: https://zabbixserver/zabbix/api_jsonrpc.php
  30. # zbx_user: Admin
  31. # zbx_password: zabbix
  32. # name: Test Graph
  33. # height: 300
  34. # width: 500
  35. # graph_items:
  36. # - item_name: openshift.master.etcd.create.fail
  37. # color: red
  38. # line_style: bold
  39. # - item_name: openshift.master.etcd.create.success
  40. # color: red
  41. # line_style: bold
  42. #
  43. #
  44. # This is in place because each module looks similar to each other.
  45. # These need duplicate code as their behavior is very similar
  46. # but different for each zabbix class.
  47. # pylint: disable=duplicate-code
  48. # pylint: disable=import-error
  49. from openshift_tools.zbxapi import ZabbixAPI, ZabbixConnection
  50. def exists(content, key='result'):
  51. ''' Check if key exists in content or the size of content[key] > 0
  52. '''
  53. if not content.has_key(key):
  54. return False
  55. if not content[key]:
  56. return False
  57. return True
  58. def get_graph_type(graphtype):
  59. '''
  60. Possible values:
  61. 0 - normal;
  62. 1 - stacked;
  63. 2 - pie;
  64. 3 - exploded;
  65. '''
  66. gtype = 0
  67. if 'stacked' in graphtype:
  68. gtype = 1
  69. elif 'pie' in graphtype:
  70. gtype = 2
  71. elif 'exploded' in graphtype:
  72. gtype = 3
  73. return gtype
  74. def get_show_legend(show_legend):
  75. '''Get the value for show_legend
  76. 0 - hide
  77. 1 - (default) show
  78. '''
  79. rval = 1
  80. if 'hide' == show_legend:
  81. rval = 0
  82. return rval
  83. def get_template_id(zapi, template_name):
  84. '''
  85. get related templates
  86. '''
  87. # Fetch templates by name
  88. content = zapi.get_content('template',
  89. 'get',
  90. {'filter': {'host': template_name},})
  91. if content.has_key('result'):
  92. return content['result'][0]['templateid']
  93. return None
  94. def get_color(color_in):
  95. ''' Receive a color and translate it to a hex representation of the color
  96. Will have a few setup by default
  97. '''
  98. colors = {'black': '000000',
  99. 'red': 'FF0000',
  100. 'pink': 'FFC0CB',
  101. 'purple': '800080',
  102. 'orange': 'FFA500',
  103. 'gold': 'FFD700',
  104. 'yellow': 'FFFF00',
  105. 'green': '008000',
  106. 'cyan': '00FFFF',
  107. 'aqua': '00FFFF',
  108. 'blue': '0000FF',
  109. 'brown': 'A52A2A',
  110. 'gray': '808080',
  111. 'grey': '808080',
  112. 'silver': 'C0C0C0',
  113. }
  114. if colors.has_key(color_in):
  115. return colors[color_in]
  116. return color_in
  117. def get_line_style(style):
  118. '''determine the line style
  119. '''
  120. line_style = {'line': 0,
  121. 'filled': 1,
  122. 'bold': 2,
  123. 'dot': 3,
  124. 'dashed': 4,
  125. 'gradient': 5,
  126. }
  127. if line_style.has_key(style):
  128. return line_style[style]
  129. return 0
  130. def get_calc_function(func):
  131. '''Determine the caclulation function'''
  132. rval = 2 # default to avg
  133. if 'min' in func:
  134. rval = 1
  135. elif 'max' in func:
  136. rval = 4
  137. elif 'all' in func:
  138. rval = 7
  139. elif 'last' in func:
  140. rval = 9
  141. return rval
  142. def get_graph_item_type(gtype):
  143. '''Determine the graph item type
  144. '''
  145. rval = 0 # simple graph type
  146. if 'sum' in gtype:
  147. rval = 2
  148. return rval
  149. def get_graph_items(zapi, gitems):
  150. '''Get graph items by id'''
  151. r_items = []
  152. for item in gitems:
  153. content = zapi.get_content('item',
  154. 'get',
  155. {'filter': {'name': item['item_name']}})
  156. _ = item.pop('item_name')
  157. color = get_color(item.pop('color'))
  158. drawtype = get_line_style(item.get('line_style', 'line'))
  159. func = get_calc_function(item.get('calc_func', 'avg'))
  160. g_type = get_graph_item_type(item.get('graph_item_type', 'simple'))
  161. if content.has_key('result'):
  162. tmp = {'itemid': content['result'][0]['itemid'],
  163. 'color': color,
  164. 'drawtype': drawtype,
  165. 'calc_fnc': func,
  166. 'type': g_type,
  167. }
  168. r_items.append(tmp)
  169. return r_items
  170. def compare_gitems(zabbix_items, user_items):
  171. '''Compare zabbix results with the user's supplied items
  172. return True if user_items are equal
  173. return False if any of the values differ
  174. '''
  175. if len(zabbix_items) != len(user_items):
  176. return False
  177. for u_item in user_items:
  178. for z_item in zabbix_items:
  179. if u_item['itemid'] == z_item['itemid']:
  180. if not all([str(value) == z_item[key] for key, value in u_item.items()]):
  181. return False
  182. return True
  183. # The branches are needed for CRUD and error handling
  184. # pylint: disable=too-many-branches
  185. def main():
  186. '''
  187. ansible zabbix module for zbx_graphs
  188. '''
  189. module = AnsibleModule(
  190. argument_spec=dict(
  191. zbx_server=dict(default='https://localhost/zabbix/api_jsonrpc.php', type='str'),
  192. zbx_user=dict(default=os.environ.get('ZABBIX_USER', None), type='str'),
  193. zbx_password=dict(default=os.environ.get('ZABBIX_PASSWORD', None), type='str'),
  194. zbx_debug=dict(default=False, type='bool'),
  195. name=dict(default=None, type='str'),
  196. height=dict(default=None, type='int'),
  197. width=dict(default=None, type='int'),
  198. graph_type=dict(default='normal', type='str'),
  199. show_legend=dict(default='show', type='str'),
  200. state=dict(default='present', type='str'),
  201. graph_items=dict(default=None, type='list'),
  202. ),
  203. #supports_check_mode=True
  204. )
  205. zapi = ZabbixAPI(ZabbixConnection(module.params['zbx_server'],
  206. module.params['zbx_user'],
  207. module.params['zbx_password'],
  208. module.params['zbx_debug']))
  209. #Set the instance and the template for the rest of the calls
  210. zbx_class_name = 'graph'
  211. state = module.params['state']
  212. content = zapi.get_content(zbx_class_name,
  213. 'get',
  214. {'filter': {'name': module.params['name']},
  215. #'templateids': templateid,
  216. 'selectGraphItems': 'extend',
  217. })
  218. #******#
  219. # GET
  220. #******#
  221. if state == 'list':
  222. module.exit_json(changed=False, results=content['result'], state="list")
  223. #******#
  224. # DELETE
  225. #******#
  226. if state == 'absent':
  227. if not exists(content):
  228. module.exit_json(changed=False, state="absent")
  229. content = zapi.get_content(zbx_class_name, 'delete', [content['result'][0]['graphid']])
  230. module.exit_json(changed=True, results=content['result'], state="absent")
  231. # Create and Update
  232. if state == 'present':
  233. params = {'name': module.params['name'],
  234. 'height': module.params['height'],
  235. 'width': module.params['width'],
  236. 'graphtype': get_graph_type(module.params['graph_type']),
  237. 'show_legend': get_show_legend(module.params['show_legend']),
  238. 'gitems': get_graph_items(zapi, module.params['graph_items']),
  239. }
  240. # Remove any None valued params
  241. _ = [params.pop(key, None) for key in params.keys() if params[key] is None]
  242. #******#
  243. # CREATE
  244. #******#
  245. if not exists(content):
  246. content = zapi.get_content(zbx_class_name, 'create', params)
  247. if content.has_key('error'):
  248. module.exit_json(failed=True, changed=True, results=content['error'], state="present")
  249. module.exit_json(changed=True, results=content['result'], state='present')
  250. ########
  251. # UPDATE
  252. ########
  253. differences = {}
  254. zab_results = content['result'][0]
  255. for key, value in params.items():
  256. if key == 'gitems':
  257. if not compare_gitems(zab_results[key], value):
  258. differences[key] = value
  259. elif zab_results[key] != value and zab_results[key] != str(value):
  260. differences[key] = value
  261. if not differences:
  262. module.exit_json(changed=False, results=zab_results, state="present")
  263. # We have differences and need to update
  264. differences['graphid'] = zab_results['graphid']
  265. content = zapi.get_content(zbx_class_name, 'update', differences)
  266. if content.has_key('error'):
  267. module.exit_json(failed=True, changed=False, results=content['error'], state="present")
  268. module.exit_json(changed=True, results=content['result'], state="present")
  269. module.exit_json(failed=True,
  270. changed=False,
  271. results='Unknown state passed. %s' % state,
  272. state="unknown")
  273. # pylint: disable=redefined-builtin, unused-wildcard-import, wildcard-import, locally-disabled
  274. # import module snippets. This are required
  275. from ansible.module_utils.basic import *
  276. main()