zbx_action.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690
  1. #!/usr/bin/env python
  2. # vim: expandtab:tabstop=4:shiftwidth=4
  3. '''
  4. Ansible module for zabbix actions
  5. '''
  6. #
  7. # Zabbix action 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. # This is in place because each module looks similar to each other.
  25. # These need duplicate code as their behavior is very similar
  26. # but different for each zabbix class.
  27. # pylint: disable=duplicate-code
  28. # pylint: disable=import-error
  29. from openshift_tools.monitoring.zbxapi import ZabbixAPI, ZabbixConnection, ZabbixAPIError
  30. CUSTOM_SCRIPT_ACTION = '0'
  31. IPMI_ACTION = '1'
  32. SSH_ACTION = '2'
  33. TELNET_ACTION = '3'
  34. GLOBAL_SCRIPT_ACTION = '4'
  35. EXECUTE_ON_ZABBIX_AGENT = '0'
  36. EXECUTE_ON_ZABBIX_SERVER = '1'
  37. OPERATION_REMOTE_COMMAND = '1'
  38. def exists(content, key='result'):
  39. ''' Check if key exists in content or the size of content[key] > 0
  40. '''
  41. if not content.has_key(key):
  42. return False
  43. if not content[key]:
  44. return False
  45. return True
  46. def conditions_equal(zab_conditions, user_conditions):
  47. '''Compare two lists of conditions'''
  48. c_type = 'conditiontype'
  49. _op = 'operator'
  50. val = 'value'
  51. if len(user_conditions) != len(zab_conditions):
  52. return False
  53. for zab_cond, user_cond in zip(zab_conditions, user_conditions):
  54. if zab_cond[c_type] != str(user_cond[c_type]) or zab_cond[_op] != str(user_cond[_op]) or \
  55. zab_cond[val] != str(user_cond[val]):
  56. return False
  57. return True
  58. def filter_differences(zabbix_filters, user_filters):
  59. '''Determine the differences from user and zabbix for operations'''
  60. rval = {}
  61. for key, val in user_filters.items():
  62. if key == 'conditions':
  63. if not conditions_equal(zabbix_filters[key], val):
  64. rval[key] = val
  65. elif zabbix_filters[key] != str(val):
  66. rval[key] = val
  67. return rval
  68. def opconditions_diff(zab_val, user_val):
  69. ''' Report whether there are differences between opconditions on
  70. zabbix and opconditions supplied by user '''
  71. if len(zab_val) != len(user_val):
  72. return True
  73. for z_cond, u_cond in zip(zab_val, user_val):
  74. if not all([str(u_cond[op_key]) == z_cond[op_key] for op_key in \
  75. ['conditiontype', 'operator', 'value']]):
  76. return True
  77. return False
  78. def opmessage_diff(zab_val, user_val):
  79. ''' Report whether there are differences between opmessage on
  80. zabbix and opmessage supplied by user '''
  81. for op_msg_key, op_msg_val in user_val.items():
  82. if zab_val[op_msg_key] != str(op_msg_val):
  83. return True
  84. return False
  85. def opmessage_grp_diff(zab_val, user_val):
  86. ''' Report whether there are differences between opmessage_grp
  87. on zabbix and opmessage_grp supplied by user '''
  88. zab_grp_ids = set([ugrp['usrgrpid'] for ugrp in zab_val])
  89. usr_grp_ids = set([ugrp['usrgrpid'] for ugrp in user_val])
  90. if usr_grp_ids != zab_grp_ids:
  91. return True
  92. return False
  93. def opmessage_usr_diff(zab_val, user_val):
  94. ''' Report whether there are differences between opmessage_usr
  95. on zabbix and opmessage_usr supplied by user '''
  96. zab_usr_ids = set([usr['usrid'] for usr in zab_val])
  97. usr_ids = set([usr['usrid'] for usr in user_val])
  98. if usr_ids != zab_usr_ids:
  99. return True
  100. return False
  101. def opcommand_diff(zab_op_cmd, usr_op_cmd):
  102. ''' Check whether user-provided opcommand matches what's already
  103. stored in Zabbix '''
  104. for usr_op_cmd_key, usr_op_cmd_val in usr_op_cmd.items():
  105. if zab_op_cmd[usr_op_cmd_key] != str(usr_op_cmd_val):
  106. return True
  107. return False
  108. def host_in_zabbix(zab_hosts, usr_host):
  109. ''' Check whether a particular user host is already in the
  110. Zabbix list of hosts '''
  111. for usr_hst_key, usr_hst_val in usr_host.items():
  112. for zab_host in zab_hosts:
  113. if usr_hst_key in zab_host and \
  114. zab_host[usr_hst_key] == str(usr_hst_val):
  115. return True
  116. return False
  117. def hostlist_in_zabbix(zab_hosts, usr_hosts):
  118. ''' Check whether user-provided list of hosts are already in
  119. the Zabbix action '''
  120. if len(zab_hosts) != len(usr_hosts):
  121. return False
  122. for usr_host in usr_hosts:
  123. if not host_in_zabbix(zab_hosts, usr_host):
  124. return False
  125. return True
  126. # We are comparing two lists of dictionaries (the one stored on zabbix and the
  127. # one the user is providing). For each type of operation, determine whether there
  128. # is a difference between what is stored on zabbix and what the user is providing.
  129. # If there is a difference, we take the user-provided data for what needs to
  130. # be stored/updated into zabbix.
  131. def operation_differences(zabbix_ops, user_ops):
  132. '''Determine the differences from user and zabbix for operations'''
  133. # if they don't match, take the user options
  134. if len(zabbix_ops) != len(user_ops):
  135. return user_ops
  136. rval = {}
  137. for zab, user in zip(zabbix_ops, user_ops):
  138. for oper in user.keys():
  139. if oper == 'opconditions' and opconditions_diff(zab[oper], \
  140. user[oper]):
  141. rval[oper] = user[oper]
  142. elif oper == 'opmessage' and opmessage_diff(zab[oper], \
  143. user[oper]):
  144. rval[oper] = user[oper]
  145. elif oper == 'opmessage_grp' and opmessage_grp_diff(zab[oper], \
  146. user[oper]):
  147. rval[oper] = user[oper]
  148. elif oper == 'opmessage_usr' and opmessage_usr_diff(zab[oper], \
  149. user[oper]):
  150. rval[oper] = user[oper]
  151. elif oper == 'opcommand' and opcommand_diff(zab[oper], \
  152. user[oper]):
  153. rval[oper] = user[oper]
  154. # opcommand_grp can be treated just like opcommand_hst
  155. # as opcommand_grp[] is just a list of groups
  156. elif oper == 'opcommand_hst' or oper == 'opcommand_grp':
  157. if not hostlist_in_zabbix(zab[oper], user[oper]):
  158. rval[oper] = user[oper]
  159. # if it's any other type of operation than the ones tested above
  160. # just do a direct compare
  161. elif oper not in ['opconditions', 'opmessage', 'opmessage_grp',
  162. 'opmessage_usr', 'opcommand', 'opcommand_hst',
  163. 'opcommand_grp'] \
  164. and str(zab[oper]) != str(user[oper]):
  165. rval[oper] = user[oper]
  166. return rval
  167. def get_users(zapi, users):
  168. '''get the mediatype id from the mediatype name'''
  169. rval_users = []
  170. for user in users:
  171. content = zapi.get_content('user',
  172. 'get',
  173. {'filter': {'alias': user}})
  174. rval_users.append({'userid': content['result'][0]['userid']})
  175. return rval_users
  176. def get_user_groups(zapi, groups):
  177. '''get the mediatype id from the mediatype name'''
  178. user_groups = []
  179. for group in groups:
  180. content = zapi.get_content('usergroup',
  181. 'get',
  182. {'search': {'name': group}})
  183. for result in content['result']:
  184. user_groups.append({'usrgrpid': result['usrgrpid']})
  185. return user_groups
  186. def get_mediatype_id_by_name(zapi, m_name):
  187. '''get the mediatype id from the mediatype name'''
  188. content = zapi.get_content('mediatype',
  189. 'get',
  190. {'filter': {'description': m_name}})
  191. return content['result'][0]['mediatypeid']
  192. def get_priority(priority):
  193. ''' determine priority
  194. '''
  195. prior = 0
  196. if 'info' in priority:
  197. prior = 1
  198. elif 'warn' in priority:
  199. prior = 2
  200. elif 'avg' == priority or 'ave' in priority:
  201. prior = 3
  202. elif 'high' in priority:
  203. prior = 4
  204. elif 'dis' in priority:
  205. prior = 5
  206. return prior
  207. def get_event_source(from_src):
  208. '''Translate even str into value'''
  209. choices = ['trigger', 'discovery', 'auto', 'internal']
  210. rval = 0
  211. try:
  212. rval = choices.index(from_src)
  213. except ValueError as _:
  214. ZabbixAPIError('Value not found for event source [%s]' % from_src)
  215. return rval
  216. def get_status(inc_status):
  217. '''determine status for action'''
  218. rval = 1
  219. if inc_status == 'enabled':
  220. rval = 0
  221. return rval
  222. def get_condition_operator(inc_operator):
  223. ''' determine the condition operator'''
  224. vals = {'=': 0,
  225. '<>': 1,
  226. 'like': 2,
  227. 'not like': 3,
  228. 'in': 4,
  229. '>=': 5,
  230. '<=': 6,
  231. 'not in': 7,
  232. }
  233. return vals[inc_operator]
  234. def get_host_id_by_name(zapi, host_name):
  235. '''Get host id by name'''
  236. content = zapi.get_content('host',
  237. 'get',
  238. {'filter': {'name': host_name}})
  239. return content['result'][0]['hostid']
  240. def get_trigger_value(inc_trigger):
  241. '''determine the proper trigger value'''
  242. rval = 1
  243. if inc_trigger == 'PROBLEM':
  244. rval = 1
  245. else:
  246. rval = 0
  247. return rval
  248. def get_template_id_by_name(zapi, t_name):
  249. '''get the template id by name'''
  250. content = zapi.get_content('template',
  251. 'get',
  252. {'filter': {'host': t_name}})
  253. return content['result'][0]['templateid']
  254. def get_host_group_id_by_name(zapi, hg_name):
  255. '''Get hostgroup id by name'''
  256. content = zapi.get_content('hostgroup',
  257. 'get',
  258. {'filter': {'name': hg_name}})
  259. return content['result'][0]['groupid']
  260. def get_condition_type(event_source, inc_condition):
  261. '''determine the condition type'''
  262. c_types = {}
  263. if event_source == 'trigger':
  264. c_types = {'host group': 0,
  265. 'host': 1,
  266. 'trigger': 2,
  267. 'trigger name': 3,
  268. 'trigger severity': 4,
  269. 'trigger value': 5,
  270. 'time period': 6,
  271. 'host template': 13,
  272. 'application': 15,
  273. 'maintenance status': 16,
  274. }
  275. elif event_source == 'discovery':
  276. c_types = {'host IP': 7,
  277. 'discovered service type': 8,
  278. 'discovered service port': 9,
  279. 'discovery status': 10,
  280. 'uptime or downtime duration': 11,
  281. 'received value': 12,
  282. 'discovery rule': 18,
  283. 'discovery check': 19,
  284. 'proxy': 20,
  285. 'discovery object': 21,
  286. }
  287. elif event_source == 'auto':
  288. c_types = {'proxy': 20,
  289. 'host name': 22,
  290. 'host metadata': 24,
  291. }
  292. elif event_source == 'internal':
  293. c_types = {'host group': 0,
  294. 'host': 1,
  295. 'host template': 13,
  296. 'application': 15,
  297. 'event type': 23,
  298. }
  299. else:
  300. raise ZabbixAPIError('Unkown event source %s' % event_source)
  301. return c_types[inc_condition]
  302. def get_operation_type(inc_operation):
  303. ''' determine the correct operation type'''
  304. o_types = {'send message': 0,
  305. 'remote command': OPERATION_REMOTE_COMMAND,
  306. 'add host': 2,
  307. 'remove host': 3,
  308. 'add to host group': 4,
  309. 'remove from host group': 5,
  310. 'link to template': 6,
  311. 'unlink from template': 7,
  312. 'enable host': 8,
  313. 'disable host': 9,
  314. }
  315. return o_types[inc_operation]
  316. def get_opcommand_type(opcommand_type):
  317. ''' determine the opcommand type '''
  318. oc_types = {'custom script': CUSTOM_SCRIPT_ACTION,
  319. 'IPMI': IPMI_ACTION,
  320. 'SSH': SSH_ACTION,
  321. 'Telnet': TELNET_ACTION,
  322. 'global script': GLOBAL_SCRIPT_ACTION,
  323. }
  324. return oc_types[opcommand_type]
  325. def get_execute_on(execute_on):
  326. ''' determine the execution target '''
  327. e_types = {'zabbix agent': EXECUTE_ON_ZABBIX_AGENT,
  328. 'zabbix server': EXECUTE_ON_ZABBIX_SERVER,
  329. }
  330. return e_types[execute_on]
  331. def action_remote_command(ansible_module, zapi, operation):
  332. ''' Process remote command type of actions '''
  333. if 'type' not in operation['opcommand']:
  334. ansible_module.exit_json(failed=True, changed=False, state='unknown',
  335. results="No Operation Type provided")
  336. operation['opcommand']['type'] = get_opcommand_type(operation['opcommand']['type'])
  337. if operation['opcommand']['type'] == CUSTOM_SCRIPT_ACTION:
  338. if 'execute_on' in operation['opcommand']:
  339. operation['opcommand']['execute_on'] = get_execute_on(operation['opcommand']['execute_on'])
  340. # custom script still requires the target hosts/groups to be set
  341. operation['opcommand_hst'] = []
  342. operation['opcommand_grp'] = []
  343. for usr_host in operation['target_hosts']:
  344. if usr_host['target_type'] == 'zabbix server':
  345. # 0 = target host local/current host
  346. operation['opcommand_hst'].append({'hostid': 0})
  347. elif usr_host['target_type'] == 'group':
  348. group_name = usr_host['target']
  349. gid = get_host_group_id_by_name(zapi, group_name)
  350. operation['opcommand_grp'].append({'groupid': gid})
  351. elif usr_host['target_type'] == 'host':
  352. host_name = usr_host['target']
  353. hid = get_host_id_by_name(zapi, host_name)
  354. operation['opcommand_hst'].append({'hostid': hid})
  355. # 'target_hosts' is just to make it easier to build zbx_actions
  356. # not part of ZabbixAPI
  357. del operation['target_hosts']
  358. else:
  359. ansible_module.exit_json(failed=True, changed=False, state='unknown',
  360. results="Unsupported remote command type")
  361. def get_action_operations(ansible_module, zapi, inc_operations):
  362. '''Convert the operations into syntax for api'''
  363. for operation in inc_operations:
  364. operation['operationtype'] = get_operation_type(operation['operationtype'])
  365. if operation['operationtype'] == 0: # send message. Need to fix the
  366. operation['opmessage']['mediatypeid'] = \
  367. get_mediatype_id_by_name(zapi, operation['opmessage']['mediatypeid'])
  368. operation['opmessage_grp'] = get_user_groups(zapi, operation.get('opmessage_grp', []))
  369. operation['opmessage_usr'] = get_users(zapi, operation.get('opmessage_usr', []))
  370. if operation['opmessage']['default_msg']:
  371. operation['opmessage']['default_msg'] = 1
  372. else:
  373. operation['opmessage']['default_msg'] = 0
  374. elif operation['operationtype'] == OPERATION_REMOTE_COMMAND:
  375. action_remote_command(ansible_module, zapi, operation)
  376. # Handle Operation conditions:
  377. # Currently there is only 1 available which
  378. # is 'event acknowledged'. In the future
  379. # if there are any added we will need to pass this
  380. # option to a function and return the correct conditiontype
  381. if operation.has_key('opconditions'):
  382. for condition in operation['opconditions']:
  383. if condition['conditiontype'] == 'event acknowledged':
  384. condition['conditiontype'] = 14
  385. if condition['operator'] == '=':
  386. condition['operator'] = 0
  387. if condition['value'] == 'acknowledged':
  388. condition['value'] = 1
  389. else:
  390. condition['value'] = 0
  391. return inc_operations
  392. def get_operation_evaltype(inc_type):
  393. '''get the operation evaltype'''
  394. rval = 0
  395. if inc_type == 'and/or':
  396. rval = 0
  397. elif inc_type == 'and':
  398. rval = 1
  399. elif inc_type == 'or':
  400. rval = 2
  401. elif inc_type == 'custom':
  402. rval = 3
  403. return rval
  404. def get_action_conditions(zapi, event_source, inc_conditions):
  405. '''Convert the conditions into syntax for api'''
  406. calc_type = inc_conditions.pop('calculation_type')
  407. inc_conditions['evaltype'] = get_operation_evaltype(calc_type)
  408. for cond in inc_conditions['conditions']:
  409. cond['operator'] = get_condition_operator(cond['operator'])
  410. # Based on conditiontype we need to set the proper value
  411. # e.g. conditiontype = hostgroup then the value needs to be a hostgroup id
  412. # e.g. conditiontype = host the value needs to be a host id
  413. cond['conditiontype'] = get_condition_type(event_source, cond['conditiontype'])
  414. if cond['conditiontype'] == 0:
  415. cond['value'] = get_host_group_id_by_name(zapi, cond['value'])
  416. elif cond['conditiontype'] == 1:
  417. cond['value'] = get_host_id_by_name(zapi, cond['value'])
  418. elif cond['conditiontype'] == 4:
  419. cond['value'] = get_priority(cond['value'])
  420. elif cond['conditiontype'] == 5:
  421. cond['value'] = get_trigger_value(cond['value'])
  422. elif cond['conditiontype'] == 13:
  423. cond['value'] = get_template_id_by_name(zapi, cond['value'])
  424. elif cond['conditiontype'] == 16:
  425. cond['value'] = ''
  426. return inc_conditions
  427. def get_send_recovery(send_recovery):
  428. '''Get the integer value'''
  429. rval = 0
  430. if send_recovery:
  431. rval = 1
  432. return rval
  433. # The branches are needed for CRUD and error handling
  434. # pylint: disable=too-many-branches
  435. def main():
  436. '''
  437. ansible zabbix module for zbx_item
  438. '''
  439. module = AnsibleModule(
  440. argument_spec=dict(
  441. zbx_server=dict(default='https://localhost/zabbix/api_jsonrpc.php', type='str'),
  442. zbx_user=dict(default=os.environ.get('ZABBIX_USER', None), type='str'),
  443. zbx_password=dict(default=os.environ.get('ZABBIX_PASSWORD', None), type='str'),
  444. zbx_debug=dict(default=False, type='bool'),
  445. name=dict(default=None, type='str'),
  446. event_source=dict(default='trigger', choices=['trigger', 'discovery', 'auto', 'internal'], type='str'),
  447. action_subject=dict(default="{TRIGGER.NAME}: {TRIGGER.STATUS}", type='str'),
  448. action_message=dict(default="{TRIGGER.NAME}: {TRIGGER.STATUS}\r\n" +
  449. "Last value: {ITEM.LASTVALUE}\r\n\r\n{TRIGGER.URL}", type='str'),
  450. reply_subject=dict(default="{TRIGGER.NAME}: {TRIGGER.STATUS}", type='str'),
  451. reply_message=dict(default="Trigger: {TRIGGER.NAME}\r\nTrigger status: {TRIGGER.STATUS}\r\n" +
  452. "Trigger severity: {TRIGGER.SEVERITY}\r\nTrigger URL: {TRIGGER.URL}\r\n\r\n" +
  453. "Item values:\r\n\r\n1. {ITEM.NAME1} ({HOST.NAME1}:{ITEM.KEY1}): " +
  454. "{ITEM.VALUE1}\r\n2. {ITEM.NAME2} ({HOST.NAME2}:{ITEM.KEY2}): " +
  455. "{ITEM.VALUE2}\r\n3. {ITEM.NAME3} ({HOST.NAME3}:{ITEM.KEY3}): " +
  456. "{ITEM.VALUE3}", type='str'),
  457. send_recovery=dict(default=False, type='bool'),
  458. status=dict(default=None, type='str'),
  459. escalation_time=dict(default=60, type='int'),
  460. conditions_filter=dict(default=None, type='dict'),
  461. operations=dict(default=None, type='list'),
  462. state=dict(default='present', type='str'),
  463. ),
  464. #supports_check_mode=True
  465. )
  466. zapi = ZabbixAPI(ZabbixConnection(module.params['zbx_server'],
  467. module.params['zbx_user'],
  468. module.params['zbx_password'],
  469. module.params['zbx_debug']))
  470. #Set the instance and the template for the rest of the calls
  471. zbx_class_name = 'action'
  472. state = module.params['state']
  473. content = zapi.get_content(zbx_class_name,
  474. 'get',
  475. {'search': {'name': module.params['name']},
  476. 'selectFilter': 'extend',
  477. 'selectOperations': 'extend',
  478. })
  479. #******#
  480. # GET
  481. #******#
  482. if state == 'list':
  483. module.exit_json(changed=False, results=content['result'], state="list")
  484. #******#
  485. # DELETE
  486. #******#
  487. if state == 'absent':
  488. if not exists(content):
  489. module.exit_json(changed=False, state="absent")
  490. content = zapi.get_content(zbx_class_name, 'delete', [content['result'][0]['actionid']])
  491. module.exit_json(changed=True, results=content['result'], state="absent")
  492. # Create and Update
  493. if state == 'present':
  494. conditions = get_action_conditions(zapi, module.params['event_source'], module.params['conditions_filter'])
  495. operations = get_action_operations(module, zapi,
  496. module.params['operations'])
  497. params = {'name': module.params['name'],
  498. 'esc_period': module.params['escalation_time'],
  499. 'eventsource': get_event_source(module.params['event_source']),
  500. 'status': get_status(module.params['status']),
  501. 'def_shortdata': module.params['action_subject'],
  502. 'def_longdata': module.params['action_message'],
  503. 'r_shortdata': module.params['reply_subject'],
  504. 'r_longdata': module.params['reply_message'],
  505. 'recovery_msg': get_send_recovery(module.params['send_recovery']),
  506. 'filter': conditions,
  507. 'operations': operations,
  508. }
  509. # Remove any None valued params
  510. _ = [params.pop(key, None) for key in params.keys() if params[key] is None]
  511. #******#
  512. # CREATE
  513. #******#
  514. if not exists(content):
  515. content = zapi.get_content(zbx_class_name, 'create', params)
  516. if content.has_key('error'):
  517. module.exit_json(failed=True, changed=True, results=content['error'], state="present")
  518. module.exit_json(changed=True, results=content['result'], state='present')
  519. ########
  520. # UPDATE
  521. ########
  522. _ = params.pop('hostid', None)
  523. differences = {}
  524. zab_results = content['result'][0]
  525. for key, value in params.items():
  526. if key == 'operations':
  527. ops = operation_differences(zab_results[key], value)
  528. if ops:
  529. differences[key] = ops
  530. elif key == 'filter':
  531. filters = filter_differences(zab_results[key], value)
  532. if filters:
  533. differences[key] = filters
  534. elif zab_results[key] != value and zab_results[key] != str(value):
  535. differences[key] = value
  536. if not differences:
  537. module.exit_json(changed=False, results=zab_results, state="present")
  538. # We have differences and need to update.
  539. # action update requires an id, filters, and operations
  540. differences['actionid'] = zab_results['actionid']
  541. differences['operations'] = params['operations']
  542. differences['filter'] = params['filter']
  543. content = zapi.get_content(zbx_class_name, 'update', differences)
  544. if content.has_key('error'):
  545. module.exit_json(failed=True, changed=False, results=content['error'], state="present")
  546. module.exit_json(changed=True, results=content['result'], state="present")
  547. module.exit_json(failed=True,
  548. changed=False,
  549. results='Unknown state passed. %s' % state,
  550. state="unknown")
  551. # pylint: disable=redefined-builtin, unused-wildcard-import, wildcard-import, locally-disabled
  552. # import module snippets. This are required
  553. from ansible.module_utils.basic import *
  554. main()