1"""
2Support for Zabbix
3
4:optdepends:    - zabbix server
5
6:configuration: This module is not usable until the zabbix user and zabbix password are specified either in a pillar
7    or in the minion's config file. Zabbix url should be also specified.
8
9    .. code-block:: yaml
10
11        zabbix.user: Admin
12        zabbix.password: mypassword
13        zabbix.url: http://127.0.0.1/zabbix/api_jsonrpc.php
14
15
16    Connection arguments from the minion config file can be overridden on the CLI by using arguments with
17    ``_connection_`` prefix.
18
19    .. code-block:: bash
20
21        zabbix.apiinfo_version _connection_user=Admin _connection_password=zabbix _connection_url=http://host/zabbix/
22
23:codeauthor: Jiri Kotlin <jiri.kotlin@ultimum.io>
24"""
25
26import logging
27import os
28import socket
29import urllib.error
30
31import salt.utils.data
32import salt.utils.files
33import salt.utils.http
34import salt.utils.json
35from salt.exceptions import SaltException
36from salt.utils.versions import LooseVersion as _LooseVersion
37
38log = logging.getLogger(__name__)
39
40INTERFACE_DEFAULT_PORTS = [10050, 161, 623, 12345]
41
42ZABBIX_TOP_LEVEL_OBJECTS = (
43    "hostgroup",
44    "template",
45    "host",
46    "maintenance",
47    "action",
48    "drule",
49    "service",
50    "proxy",
51    "screen",
52    "usergroup",
53    "mediatype",
54    "script",
55    "valuemap",
56)
57
58# Zabbix object and its ID name mapping
59ZABBIX_ID_MAPPER = {
60    "action": "actionid",
61    "alert": "alertid",
62    "application": "applicationid",
63    "dhost": "dhostid",
64    "dservice": "dserviceid",
65    "dcheck": "dcheckid",
66    "drule": "druleid",
67    "event": "eventid",
68    "graph": "graphid",
69    "graphitem": "gitemid",
70    "graphprototype": "graphid",
71    "history": "itemid",
72    "host": "hostid",
73    "hostgroup": "groupid",
74    "hostinterface": "interfaceid",
75    "hostprototype": "hostid",
76    "iconmap": "iconmapid",
77    "image": "imageid",
78    "item": "itemid",
79    "itemprototype": "itemid",
80    "service": "serviceid",
81    "discoveryrule": "itemid",
82    "maintenance": "maintenanceid",
83    "map": "sysmapid",
84    "usermedia": "mediaid",
85    "mediatype": "mediatypeid",
86    "proxy": "proxyid",
87    "screen": "screenid",
88    "screenitem": "screenitemid",
89    "script": "scriptid",
90    "template": "templateid",
91    "templatescreen": "screenid",
92    "templatescreenitem": "screenitemid",
93    "trend": "itemid",
94    "trigger": "triggerid",
95    "triggerprototype": "triggerid",
96    "user": "userid",
97    "usergroup": "usrgrpid",
98    "usermacro": "globalmacroid",
99    "valuemap": "valuemapid",
100    "httptest": "httptestid",
101}
102
103# Define the module's virtual name
104__virtualname__ = "zabbix"
105
106
107def __virtual__():
108    """
109    Only load the module if all modules are imported correctly.
110    """
111    return __virtualname__
112
113
114def _frontend_url():
115    """
116    Tries to guess the url of zabbix frontend.
117
118    .. versionadded:: 2016.3.0
119    """
120    hostname = socket.gethostname()
121    frontend_url = "http://" + hostname + "/zabbix/api_jsonrpc.php"
122    try:
123        try:
124            response = salt.utils.http.query(frontend_url)
125            error = response["error"]
126        except urllib.error.HTTPError as http_e:
127            error = str(http_e)
128        if error.find("412: Precondition Failed"):
129            return frontend_url
130        else:
131            raise KeyError
132    except (ValueError, KeyError):
133        return False
134
135
136def _query(method, params, url, auth=None):
137    """
138    JSON request to Zabbix API.
139
140    .. versionadded:: 2016.3.0
141
142    :param method: actual operation to perform via the API
143    :param params: parameters required for specific method
144    :param url: url of zabbix api
145    :param auth: auth token for zabbix api (only for methods with required authentication)
146
147    :return: Response from API with desired data in JSON format. In case of error returns more specific description.
148
149    .. versionchanged:: 2017.7
150    """
151
152    unauthenticated_methods = [
153        "user.login",
154        "apiinfo.version",
155    ]
156
157    header_dict = {"Content-type": "application/json"}
158    data = {"jsonrpc": "2.0", "id": 0, "method": method, "params": params}
159
160    if method not in unauthenticated_methods:
161        data["auth"] = auth
162
163    data = salt.utils.json.dumps(data)
164
165    log.info("_QUERY input:\nurl: %s\ndata: %s", str(url), str(data))
166
167    try:
168        result = salt.utils.http.query(
169            url,
170            method="POST",
171            data=data,
172            header_dict=header_dict,
173            decode_type="json",
174            decode=True,
175            status=True,
176            headers=True,
177        )
178        log.info("_QUERY result: %s", str(result))
179        if "error" in result:
180            raise SaltException(
181                "Zabbix API: Status: {} ({})".format(result["status"], result["error"])
182            )
183        ret = result.get("dict", {})
184        if "error" in ret:
185            raise SaltException(
186                "Zabbix API: {} ({})".format(
187                    ret["error"]["message"], ret["error"]["data"]
188                )
189            )
190        return ret
191    except ValueError as err:
192        raise SaltException(
193            "URL or HTTP headers are probably not correct! ({})".format(err)
194        )
195    except OSError as err:
196        raise SaltException("Check hostname in URL! ({})".format(err))
197
198
199def _login(**kwargs):
200    """
201    Log in to the API and generate the authentication token.
202
203    .. versionadded:: 2016.3.0
204
205    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
206    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
207    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
208
209    :return: On success connargs dictionary with auth token and frontend url, False on failure.
210
211    """
212    connargs = dict()
213
214    def _connarg(name, key=None):
215        """
216        Add key to connargs, only if name exists in our kwargs or, as zabbix.<name> in __opts__ or __pillar__
217
218        Evaluate in said order - kwargs, opts, then pillar. To avoid collision with other functions,
219        kwargs-based connection arguments are prefixed with 'connection_' (i.e. '_connection_user', etc.).
220
221        Inspired by mysql salt module.
222        """
223        if key is None:
224            key = name
225
226        if name in kwargs:
227            connargs[key] = kwargs[name]
228        else:
229            prefix = "_connection_"
230            if name.startswith(prefix):
231                try:
232                    name = name[len(prefix) :]
233                except IndexError:
234                    return
235            val = __salt__["config.get"]("zabbix.{}".format(name), None) or __salt__[
236                "config.get"
237            ]("zabbix:{}".format(name), None)
238            if val is not None:
239                connargs[key] = val
240
241    _connarg("_connection_user", "user")
242    _connarg("_connection_password", "password")
243    _connarg("_connection_url", "url")
244
245    if "url" not in connargs:
246        connargs["url"] = _frontend_url()
247
248    try:
249        if connargs["user"] and connargs["password"] and connargs["url"]:
250            params = {"user": connargs["user"], "password": connargs["password"]}
251            method = "user.login"
252            ret = _query(method, params, connargs["url"])
253            auth = ret["result"]
254            connargs["auth"] = auth
255            connargs.pop("user", None)
256            connargs.pop("password", None)
257            return connargs
258        else:
259            raise KeyError
260    except KeyError as err:
261        raise SaltException("URL is probably not correct! ({})".format(err))
262
263
264def _params_extend(params, _ignore_name=False, **kwargs):
265    """
266    Extends the params dictionary by values from keyword arguments.
267
268    .. versionadded:: 2016.3.0
269
270    :param params: Dictionary with parameters for zabbix API.
271    :param _ignore_name: Salt State module is passing first line as 'name' parameter. If API uses optional parameter
272    'name' (for ex. host_create, user_create method), please use 'visible_name' or 'firstname' instead of 'name' to
273    not mess these values.
274    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
275    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
276    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
277
278    :return: Extended params dictionary with parameters.
279
280    """
281    # extend params value by optional zabbix API parameters
282    for key in kwargs:
283        if not key.startswith("_"):
284            params.setdefault(key, kwargs[key])
285
286    # ignore name parameter passed from Salt state module, use firstname or visible_name instead
287    if _ignore_name:
288        params.pop("name", None)
289        if "firstname" in params:
290            params["name"] = params.pop("firstname")
291        elif "visible_name" in params:
292            params["name"] = params.pop("visible_name")
293
294    return params
295
296
297def get_zabbix_id_mapper():
298    """
299    .. versionadded:: 2017.7
300
301    Make ZABBIX_ID_MAPPER constant available to state modules.
302
303    :return: ZABBIX_ID_MAPPER
304    """
305    return ZABBIX_ID_MAPPER
306
307
308def substitute_params(input_object, extend_params=None, filter_key="name", **kwargs):
309    """
310    .. versionadded:: 2017.7
311
312    Go through Zabbix object params specification and if needed get given object ID from Zabbix API and put it back
313    as a value. Definition of the object is done via dict with keys "query_object" and "query_name".
314
315    :param input_object: Zabbix object type specified in state file
316    :param extend_params: Specify query with params
317    :param filter_key: Custom filtering key (default: name)
318    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
319    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
320    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
321
322    :return: Params structure with values converted to string for further comparison purposes
323    """
324    if extend_params is None:
325        extend_params = {}
326    if isinstance(input_object, list):
327        return [
328            substitute_params(oitem, extend_params, filter_key, **kwargs)
329            for oitem in input_object
330        ]
331    elif isinstance(input_object, dict):
332        if "query_object" in input_object:
333            query_params = {}
334            if input_object["query_object"] not in ZABBIX_TOP_LEVEL_OBJECTS:
335                query_params.update(extend_params)
336            try:
337                query_params.update(
338                    {"filter": {filter_key: input_object["query_name"]}}
339                )
340                return get_object_id_by_params(
341                    input_object["query_object"], query_params, **kwargs
342                )
343            except KeyError:
344                raise SaltException(
345                    "Qyerying object ID requested "
346                    "but object name not provided: {}".format(input_object)
347                )
348        else:
349            return {
350                key: substitute_params(val, extend_params, filter_key, **kwargs)
351                for key, val in input_object.items()
352            }
353    else:
354        # Zabbix response is always str, return everything in str as well
355        return str(input_object)
356
357
358# pylint: disable=too-many-return-statements,too-many-nested-blocks
359def compare_params(defined, existing, return_old_value=False):
360    """
361    .. versionadded:: 2017.7
362
363    Compares Zabbix object definition against existing Zabbix object.
364
365    :param defined: Zabbix object definition taken from sls file.
366    :param existing: Existing Zabbix object taken from result of an API call.
367    :param return_old_value: Default False. If True, returns dict("old"=old_val, "new"=new_val) for rollback purpose.
368    :return: Params that are different from existing object. Result extended by
369        object ID can be passed directly to Zabbix API update method.
370    """
371    # Comparison of data types
372    if not isinstance(defined, type(existing)):
373        raise SaltException(
374            "Zabbix object comparison failed (data type mismatch). Expecting {}, got"
375            ' {}. Existing value: "{}", defined value: "{}").'.format(
376                type(existing), type(defined), existing, defined
377            )
378        )
379
380    # Comparison of values
381    if not salt.utils.data.is_iter(defined):
382        if str(defined) != str(existing) and return_old_value:
383            return {"new": str(defined), "old": str(existing)}
384        elif str(defined) != str(existing) and not return_old_value:
385            return str(defined)
386
387    # Comparison of lists of values or lists of dicts
388    if isinstance(defined, list):
389        if len(defined) != len(existing):
390            log.info("Different list length!")
391            return {"new": defined, "old": existing} if return_old_value else defined
392        else:
393            difflist = []
394            for ditem in defined:
395                d_in_e = []
396                for eitem in existing:
397                    comp = compare_params(ditem, eitem, return_old_value)
398                    if return_old_value:
399                        d_in_e.append(comp["new"])
400                    else:
401                        d_in_e.append(comp)
402                if all(d_in_e):
403                    difflist.append(ditem)
404            # If there is any difference in a list then whole defined list must be returned and provided for update
405            if any(difflist) and return_old_value:
406                return {"new": defined, "old": existing}
407            elif any(difflist) and not return_old_value:
408                return defined
409
410    # Comparison of dicts
411    if isinstance(defined, dict):
412        try:
413            # defined must be a subset of existing to be compared
414            if set(defined) <= set(existing):
415                intersection = set(defined) & set(existing)
416                diffdict = {"new": {}, "old": {}} if return_old_value else {}
417                for i in intersection:
418                    comp = compare_params(defined[i], existing[i], return_old_value)
419                    if return_old_value:
420                        if comp or (not comp and isinstance(comp, list)):
421                            diffdict["new"].update({i: defined[i]})
422                            diffdict["old"].update({i: existing[i]})
423                    else:
424                        if comp or (not comp and isinstance(comp, list)):
425                            diffdict.update({i: defined[i]})
426                return diffdict
427
428            return {"new": defined, "old": existing} if return_old_value else defined
429
430        except TypeError:
431            raise SaltException(
432                "Zabbix object comparison failed (data type mismatch). Expecting {},"
433                ' got {}. Existing value: "{}", defined value: "{}").'.format(
434                    type(existing), type(defined), existing, defined
435                )
436            )
437
438
439def get_object_id_by_params(obj, params=None, **connection_args):
440    """
441    .. versionadded:: 2017.7
442
443    Get ID of single Zabbix object specified by its name.
444
445    :param obj: Zabbix object type
446    :param params: Parameters by which object is uniquely identified
447    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
448    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
449    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
450
451    :return: object ID
452    """
453    if params is None:
454        params = {}
455    res = run_query(obj + ".get", params, **connection_args)
456    if res and len(res) == 1:
457        return str(res[0][ZABBIX_ID_MAPPER[obj]])
458    else:
459        raise SaltException(
460            "Zabbix API: Object does not exist or bad Zabbix user permissions or other"
461            " unexpected result. Called method {} with params {}. Result: {}".format(
462                obj + ".get", params, res
463            )
464        )
465
466
467def apiinfo_version(**connection_args):
468    """
469    Retrieve the version of the Zabbix API.
470
471    .. versionadded:: 2016.3.0
472
473    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
474    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
475    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
476
477    :return: On success string with Zabbix API version, False on failure.
478
479    CLI Example:
480
481    .. code-block:: bash
482
483        salt '*' zabbix.apiinfo_version
484    """
485    conn_args = _login(**connection_args)
486    ret = False
487    try:
488        if conn_args:
489            method = "apiinfo.version"
490            params = {}
491            ret = _query(method, params, conn_args["url"], conn_args["auth"])
492            return ret["result"]
493        else:
494            raise KeyError
495    except KeyError:
496        return False
497
498
499def user_create(alias, passwd, usrgrps, **connection_args):
500    """
501    .. versionadded:: 2016.3.0
502
503    Create new zabbix user
504
505    .. note::
506        This function accepts all standard user properties: keyword argument
507        names differ depending on your zabbix version, see here__.
508
509        .. __: https://www.zabbix.com/documentation/2.0/manual/appendix/api/user/definitions#user
510
511    :param alias: user alias
512    :param passwd: user's password
513    :param usrgrps: user groups to add the user to
514
515    :param _connection_user: zabbix user (can also be set in opts or pillar, see module's docstring)
516    :param _connection_password: zabbix password (can also be set in opts or pillar, see module's docstring)
517    :param _connection_url: url of zabbix frontend (can also be set in opts or pillar, see module's docstring)
518
519    :param firstname: string with firstname of the user, use 'firstname' instead of 'name' parameter to not mess
520                      with value supplied from Salt sls file.
521
522    :return: On success string with id of the created user.
523
524    CLI Example:
525
526    .. code-block:: bash
527
528        salt '*' zabbix.user_create james password007 '[7, 12]' firstname='James Bond'
529    """
530    conn_args = _login(**connection_args)
531    ret = False
532    try:
533        if conn_args:
534            method = "user.create"
535            params = {"alias": alias, "passwd": passwd, "usrgrps": []}
536            # User groups
537            if not isinstance(usrgrps, list):
538                usrgrps = [usrgrps]
539            for usrgrp in usrgrps:
540                params["usrgrps"].append({"usrgrpid": usrgrp})
541
542            params = _params_extend(params, _ignore_name=True, **connection_args)
543            ret = _query(method, params, conn_args["url"], conn_args["auth"])
544            return ret["result"]["userids"]
545        else:
546            raise KeyError
547    except KeyError:
548        return ret
549
550
551def user_delete(users, **connection_args):
552    """
553    Delete zabbix users.
554
555    .. versionadded:: 2016.3.0
556
557    :param users: array of users (userids) to delete
558    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
559    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
560    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
561
562    :return: On success array with userids of deleted users.
563
564    CLI Example:
565
566    .. code-block:: bash
567
568        salt '*' zabbix.user_delete 15
569    """
570    conn_args = _login(**connection_args)
571    ret = False
572    try:
573        if conn_args:
574            method = "user.delete"
575            if not isinstance(users, list):
576                params = [users]
577            else:
578                params = users
579
580            ret = _query(method, params, conn_args["url"], conn_args["auth"])
581            return ret["result"]["userids"]
582        else:
583            raise KeyError
584    except KeyError:
585        return ret
586
587
588def user_exists(alias, **connection_args):
589    """
590    Checks if user with given alias exists.
591
592    .. versionadded:: 2016.3.0
593
594    :param alias: user alias
595    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
596    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
597    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
598
599    :return: True if user exists, else False.
600
601    CLI Example:
602
603    .. code-block:: bash
604
605        salt '*' zabbix.user_exists james
606    """
607    conn_args = _login(**connection_args)
608    ret = False
609    try:
610        if conn_args:
611            method = "user.get"
612            params = {"output": "extend", "filter": {"alias": alias}}
613            ret = _query(method, params, conn_args["url"], conn_args["auth"])
614            return True if len(ret["result"]) > 0 else False
615        else:
616            raise KeyError
617    except KeyError:
618        return ret
619
620
621def user_get(alias=None, userids=None, **connection_args):
622    """
623    Retrieve users according to the given parameters.
624
625    .. versionadded:: 2016.3.0
626
627    :param alias: user alias
628    :param userids: return only users with the given IDs
629    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
630    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
631    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
632
633    :return: Array with details of convenient users, False on failure of if no user found.
634
635    CLI Example:
636
637    .. code-block:: bash
638
639        salt '*' zabbix.user_get james
640    """
641    conn_args = _login(**connection_args)
642    ret = False
643    try:
644        if conn_args:
645            method = "user.get"
646            params = {"output": "extend", "filter": {}}
647            if not userids and not alias:
648                return {
649                    "result": False,
650                    "comment": (
651                        "Please submit alias or userids parameter to retrieve users."
652                    ),
653                }
654            if alias:
655                params["filter"].setdefault("alias", alias)
656            if userids:
657                params.setdefault("userids", userids)
658            params = _params_extend(params, **connection_args)
659            ret = _query(method, params, conn_args["url"], conn_args["auth"])
660            return ret["result"] if len(ret["result"]) > 0 else False
661        else:
662            raise KeyError
663    except KeyError:
664        return ret
665
666
667def user_update(userid, **connection_args):
668    """
669    .. versionadded:: 2016.3.0
670
671    Update existing users
672
673    .. note::
674        This function accepts all standard user properties: keyword argument
675        names differ depending on your zabbix version, see here__.
676
677        .. __: https://www.zabbix.com/documentation/2.0/manual/appendix/api/user/definitions#user
678
679    :param userid: id of the user to update
680    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
681    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
682    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
683
684    :return: Id of the updated user on success.
685
686    CLI Example:
687
688    .. code-block:: bash
689
690        salt '*' zabbix.user_update 16 visible_name='James Brown'
691    """
692    conn_args = _login(**connection_args)
693    ret = False
694    try:
695        if conn_args:
696            method = "user.update"
697            params = {
698                "userid": userid,
699            }
700            params = _params_extend(params, _ignore_name=True, **connection_args)
701            ret = _query(method, params, conn_args["url"], conn_args["auth"])
702            return ret["result"]["userids"]
703        else:
704            raise KeyError
705    except KeyError:
706        return ret
707
708
709def user_getmedia(userids=None, **connection_args):
710    """
711    .. versionadded:: 2016.3.0
712
713    Retrieve media according to the given parameters
714
715    .. note::
716        This function accepts all standard usermedia.get properties: keyword
717        argument names differ depending on your zabbix version, see here__.
718
719        .. __: https://www.zabbix.com/documentation/3.2/manual/api/reference/usermedia/get
720
721    :param userids: return only media that are used by the given users
722
723    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
724    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
725    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
726
727    :return: List of retrieved media, False on failure.
728
729    CLI Example:
730
731    .. code-block:: bash
732
733        salt '*' zabbix.user_getmedia
734    """
735    conn_args = _login(**connection_args)
736    ret = False
737    try:
738        if conn_args:
739            method = "usermedia.get"
740            if userids:
741                params = {"userids": userids}
742            else:
743                params = {}
744            params = _params_extend(params, **connection_args)
745            ret = _query(method, params, conn_args["url"], conn_args["auth"])
746            return ret["result"]
747        else:
748            raise KeyError
749    except KeyError:
750        return ret
751
752
753def user_addmedia(
754    userids, active, mediatypeid, period, sendto, severity, **connection_args
755):
756    """
757    Add new media to multiple users.
758
759    .. versionadded:: 2016.3.0
760
761    :param userids: ID of the user that uses the media
762    :param active: Whether the media is enabled (0 enabled, 1 disabled)
763    :param mediatypeid: ID of the media type used by the media
764    :param period: Time when the notifications can be sent as a time period
765    :param sendto: Address, user name or other identifier of the recipient
766    :param severity: Trigger severities to send notifications about
767    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
768    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
769    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
770
771    :return: IDs of the created media.
772
773    CLI Example:
774
775    .. code-block:: bash
776
777        salt '*' zabbix.user_addmedia 4 active=0 mediatypeid=1 period='1-7,00:00-24:00' sendto='support2@example.com'
778        severity=63
779
780    """
781    conn_args = _login(**connection_args)
782    ret = False
783    try:
784        if conn_args:
785            method = "user.addmedia"
786            params = {"users": []}
787            # Users
788            if not isinstance(userids, list):
789                userids = [userids]
790            for user in userids:
791                params["users"].append({"userid": user})
792            # Medias
793            params["medias"] = [
794                {
795                    "active": active,
796                    "mediatypeid": mediatypeid,
797                    "period": period,
798                    "sendto": sendto,
799                    "severity": severity,
800                },
801            ]
802
803            ret = _query(method, params, conn_args["url"], conn_args["auth"])
804            return ret["result"]["mediaids"]
805        else:
806            raise KeyError
807    except KeyError:
808        return ret
809
810
811def user_deletemedia(mediaids, **connection_args):
812    """
813    Delete media by id.
814
815    .. versionadded:: 2016.3.0
816
817    :param mediaids: IDs of the media to delete
818    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
819    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
820    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
821
822    :return: IDs of the deleted media, False on failure.
823
824    CLI Example:
825
826    .. code-block:: bash
827
828        salt '*' zabbix.user_deletemedia 27
829    """
830    conn_args = _login(**connection_args)
831    ret = False
832    try:
833        if conn_args:
834            method = "user.deletemedia"
835
836            if not isinstance(mediaids, list):
837                mediaids = [mediaids]
838            params = mediaids
839            ret = _query(method, params, conn_args["url"], conn_args["auth"])
840            return ret["result"]["mediaids"]
841        else:
842            raise KeyError
843    except KeyError:
844        return ret
845
846
847def user_list(**connection_args):
848    """
849    Retrieve all of the configured users.
850
851    .. versionadded:: 2016.3.0
852
853    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
854    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
855    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
856
857    :return: Array with user details.
858
859    CLI Example:
860
861    .. code-block:: bash
862
863        salt '*' zabbix.user_list
864    """
865    conn_args = _login(**connection_args)
866    ret = False
867    try:
868        if conn_args:
869            method = "user.get"
870            params = {"output": "extend"}
871            ret = _query(method, params, conn_args["url"], conn_args["auth"])
872            return ret["result"]
873        else:
874            raise KeyError
875    except KeyError:
876        return ret
877
878
879def usergroup_create(name, **connection_args):
880    """
881    .. versionadded:: 2016.3.0
882
883    Create new user group
884
885    .. note::
886        This function accepts all standard user group properties: keyword
887        argument names differ depending on your zabbix version, see here__.
888
889        .. __: https://www.zabbix.com/documentation/2.0/manual/appendix/api/usergroup/definitions#user_group
890
891    :param name: name of the user group
892    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
893    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
894    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
895
896    :return:  IDs of the created user groups.
897
898    CLI Example:
899
900    .. code-block:: bash
901
902        salt '*' zabbix.usergroup_create GroupName
903    """
904    conn_args = _login(**connection_args)
905    ret = False
906    try:
907        if conn_args:
908            method = "usergroup.create"
909            params = {"name": name}
910            params = _params_extend(params, **connection_args)
911            ret = _query(method, params, conn_args["url"], conn_args["auth"])
912            return ret["result"]["usrgrpids"]
913        else:
914            raise KeyError
915    except KeyError:
916        return ret
917
918
919def usergroup_delete(usergroupids, **connection_args):
920    """
921    .. versionadded:: 2016.3.0
922
923    :param usergroupids: IDs of the user groups to delete
924
925    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
926    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
927    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
928
929    :return: IDs of the deleted user groups.
930
931    CLI Example:
932
933    .. code-block:: bash
934
935        salt '*' zabbix.usergroup_delete 28
936    """
937    conn_args = _login(**connection_args)
938    ret = False
939    try:
940        if conn_args:
941            method = "usergroup.delete"
942            if not isinstance(usergroupids, list):
943                usergroupids = [usergroupids]
944            params = usergroupids
945            ret = _query(method, params, conn_args["url"], conn_args["auth"])
946            return ret["result"]["usrgrpids"]
947        else:
948            raise KeyError
949    except KeyError:
950        return ret
951
952
953def usergroup_exists(name=None, node=None, nodeids=None, **connection_args):
954    """
955    Checks if at least one user group that matches the given filter criteria exists
956
957    .. versionadded:: 2016.3.0
958
959    :param name: names of the user groups
960    :param node: name of the node the user groups must belong to (This will override the nodeids parameter.)
961    :param nodeids: IDs of the nodes the user groups must belong to
962
963    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
964    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
965    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
966
967    :return: True if at least one user group that matches the given filter criteria exists, else False.
968
969    CLI Example:
970
971    .. code-block:: bash
972
973        salt '*' zabbix.usergroup_exists Guests
974    """
975    conn_args = _login(**connection_args)
976    zabbix_version = apiinfo_version(**connection_args)
977    ret = False
978    try:
979        if conn_args:
980            # usergroup.exists deprecated
981            if _LooseVersion(zabbix_version) > _LooseVersion("2.5"):
982                if not name:
983                    name = ""
984                ret = usergroup_get(name, None, **connection_args)
985                return bool(ret)
986            # zabbix 2.4 and earlier
987            else:
988                method = "usergroup.exists"
989                params = {}
990                if not name and not node and not nodeids:
991                    return {
992                        "result": False,
993                        "comment": (
994                            "Please submit name, node or nodeids parameter to check if "
995                            "at least one user group exists."
996                        ),
997                    }
998                if name:
999                    params["name"] = name
1000                # deprecated in 2.4
1001                if _LooseVersion(zabbix_version) < _LooseVersion("2.4"):
1002                    if node:
1003                        params["node"] = node
1004                    if nodeids:
1005                        params["nodeids"] = nodeids
1006                ret = _query(method, params, conn_args["url"], conn_args["auth"])
1007                return ret["result"]
1008        else:
1009            raise KeyError
1010    except KeyError:
1011        return ret
1012
1013
1014def usergroup_get(name=None, usrgrpids=None, userids=None, **connection_args):
1015    """
1016    .. versionadded:: 2016.3.0
1017
1018    Retrieve user groups according to the given parameters
1019
1020    .. note::
1021        This function accepts all usergroup_get properties: keyword argument
1022        names differ depending on your zabbix version, see here__.
1023
1024        .. __: https://www.zabbix.com/documentation/2.4/manual/api/reference/usergroup/get
1025
1026    :param name: names of the user groups
1027    :param usrgrpids: return only user groups with the given IDs
1028    :param userids: return only user groups that contain the given users
1029    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
1030    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
1031    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
1032
1033    :return: Array with convenient user groups details, False if no user group found or on failure.
1034
1035    CLI Example:
1036
1037    .. code-block:: bash
1038
1039        salt '*' zabbix.usergroup_get Guests
1040    """
1041    conn_args = _login(**connection_args)
1042    zabbix_version = apiinfo_version(**connection_args)
1043    ret = False
1044    try:
1045        if conn_args:
1046            method = "usergroup.get"
1047            # Versions above 2.4 allow retrieving user group permissions
1048            if _LooseVersion(zabbix_version) > _LooseVersion("2.5"):
1049                params = {"selectRights": "extend", "output": "extend", "filter": {}}
1050            else:
1051                params = {"output": "extend", "filter": {}}
1052            if not name and not usrgrpids and not userids:
1053                return False
1054            if name:
1055                params["filter"].setdefault("name", name)
1056            if usrgrpids:
1057                params.setdefault("usrgrpids", usrgrpids)
1058            if userids:
1059                params.setdefault("userids", userids)
1060            params = _params_extend(params, **connection_args)
1061            ret = _query(method, params, conn_args["url"], conn_args["auth"])
1062
1063            return False if len(ret["result"]) < 1 else ret["result"]
1064        else:
1065            raise KeyError
1066    except KeyError:
1067        return ret
1068
1069
1070def usergroup_update(usrgrpid, **connection_args):
1071    """
1072    .. versionadded:: 2016.3.0
1073
1074    Update existing user group
1075
1076    .. note::
1077        This function accepts all standard user group properties: keyword
1078        argument names differ depending on your zabbix version, see here__.
1079
1080        .. __: https://www.zabbix.com/documentation/2.4/manual/api/reference/usergroup/object#user_group
1081
1082    :param usrgrpid: ID of the user group to update.
1083    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
1084    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
1085    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
1086
1087    :return: IDs of the updated user group, False on failure.
1088
1089    CLI Example:
1090
1091    .. code-block:: bash
1092
1093        salt '*' zabbix.usergroup_update 8 name=guestsRenamed
1094    """
1095    conn_args = _login(**connection_args)
1096    ret = False
1097    try:
1098        if conn_args:
1099            method = "usergroup.update"
1100            params = {"usrgrpid": usrgrpid}
1101            params = _params_extend(params, **connection_args)
1102            ret = _query(method, params, conn_args["url"], conn_args["auth"])
1103            return ret["result"]["usrgrpids"]
1104        else:
1105            raise KeyError
1106    except KeyError:
1107        return ret
1108
1109
1110def usergroup_list(**connection_args):
1111    """
1112    Retrieve all enabled user groups.
1113
1114    .. versionadded:: 2016.3.0
1115
1116    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
1117    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
1118    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
1119
1120    :return: Array with enabled user groups details, False on failure.
1121
1122    CLI Example:
1123
1124    .. code-block:: bash
1125
1126        salt '*' zabbix.usergroup_list
1127    """
1128    conn_args = _login(**connection_args)
1129    ret = False
1130    try:
1131        if conn_args:
1132            method = "usergroup.get"
1133            params = {
1134                "output": "extend",
1135            }
1136            ret = _query(method, params, conn_args["url"], conn_args["auth"])
1137            return ret["result"]
1138        else:
1139            raise KeyError
1140    except KeyError:
1141        return ret
1142
1143
1144def host_create(host, groups, interfaces, **connection_args):
1145    """
1146    .. versionadded:: 2016.3.0
1147
1148    Create new host
1149
1150    .. note::
1151        This function accepts all standard host properties: keyword argument
1152        names differ depending on your zabbix version, see here__.
1153
1154        .. __: https://www.zabbix.com/documentation/2.4/manual/api/reference/host/object#host
1155
1156    :param host: technical name of the host
1157    :param groups: groupids of host groups to add the host to
1158    :param interfaces: interfaces to be created for the host
1159    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
1160    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
1161    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
1162    :param visible_name: string with visible name of the host, use
1163        'visible_name' instead of 'name' parameter to not mess with value
1164        supplied from Salt sls file.
1165
1166    return: ID of the created host.
1167
1168    CLI Example:
1169
1170    .. code-block:: bash
1171
1172        salt '*' zabbix.host_create technicalname 4
1173        interfaces='{type: 1, main: 1, useip: 1, ip: "192.168.3.1", dns: "", port: 10050}'
1174        visible_name='Host Visible Name' inventory_mode=0 inventory='{"alias": "something"}'
1175    """
1176    conn_args = _login(**connection_args)
1177    ret = False
1178    try:
1179        if conn_args:
1180            method = "host.create"
1181            params = {"host": host}
1182            # Groups
1183            if not isinstance(groups, list):
1184                groups = [groups]
1185            grps = []
1186            for group in groups:
1187                grps.append({"groupid": group})
1188            params["groups"] = grps
1189            # Interfaces
1190            if not isinstance(interfaces, list):
1191                interfaces = [interfaces]
1192            params["interfaces"] = interfaces
1193            params = _params_extend(params, _ignore_name=True, **connection_args)
1194            ret = _query(method, params, conn_args["url"], conn_args["auth"])
1195            return ret["result"]["hostids"]
1196        else:
1197            raise KeyError
1198    except KeyError:
1199        return ret
1200
1201
1202def host_delete(hostids, **connection_args):
1203    """
1204    Delete hosts.
1205
1206    .. versionadded:: 2016.3.0
1207
1208    :param hostids: Hosts (hostids) to delete.
1209    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
1210    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
1211    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
1212
1213    :return: IDs of the deleted hosts.
1214
1215    CLI Example:
1216
1217    .. code-block:: bash
1218
1219        salt '*' zabbix.host_delete 10106
1220    """
1221    conn_args = _login(**connection_args)
1222    ret = False
1223    try:
1224        if conn_args:
1225            method = "host.delete"
1226            if not isinstance(hostids, list):
1227                params = [hostids]
1228            else:
1229                params = hostids
1230            ret = _query(method, params, conn_args["url"], conn_args["auth"])
1231            return ret["result"]["hostids"]
1232        else:
1233            raise KeyError
1234    except KeyError:
1235        return ret
1236
1237
1238def host_exists(
1239    host=None, hostid=None, name=None, node=None, nodeids=None, **connection_args
1240):
1241    """
1242    Checks if at least one host that matches the given filter criteria exists.
1243
1244    .. versionadded:: 2016.3.0
1245
1246    :param host: technical name of the host
1247    :param hostids: Hosts (hostids) to delete.
1248    :param name: visible name of the host
1249    :param node: name of the node the hosts must belong to (zabbix API < 2.4)
1250    :param nodeids: IDs of the node the hosts must belong to (zabbix API < 2.4)
1251    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
1252    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
1253    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
1254
1255    :return: IDs of the deleted hosts, False on failure.
1256
1257    CLI Example:
1258
1259    .. code-block:: bash
1260
1261        salt '*' zabbix.host_exists 'Zabbix server'
1262    """
1263    conn_args = _login(**connection_args)
1264    zabbix_version = apiinfo_version(**connection_args)
1265    ret = False
1266    try:
1267        if conn_args:
1268            # hostgroup.exists deprecated
1269            if _LooseVersion(zabbix_version) > _LooseVersion("2.5"):
1270                if not host:
1271                    host = None
1272                if not name:
1273                    name = None
1274                if not hostid:
1275                    hostid = None
1276                ret = host_get(host, name, hostid, **connection_args)
1277                return bool(ret)
1278            # zabbix 2.4 nad earlier
1279            else:
1280                method = "host.exists"
1281                params = {}
1282                if hostid:
1283                    params["hostid"] = hostid
1284                if host:
1285                    params["host"] = host
1286                if name:
1287                    params["name"] = name
1288                # deprecated in 2.4
1289                if _LooseVersion(zabbix_version) < _LooseVersion("2.4"):
1290                    if node:
1291                        params["node"] = node
1292                    if nodeids:
1293                        params["nodeids"] = nodeids
1294                if not hostid and not host and not name and not node and not nodeids:
1295                    return {
1296                        "result": False,
1297                        "comment": (
1298                            "Please submit hostid, host, name, node or nodeids"
1299                            " parameter tocheck if at least one host that matches the"
1300                            " given filter criteria exists."
1301                        ),
1302                    }
1303                ret = _query(method, params, conn_args["url"], conn_args["auth"])
1304                return ret["result"]
1305        else:
1306            raise KeyError
1307    except KeyError:
1308        return ret
1309
1310
1311def host_get(host=None, name=None, hostids=None, **connection_args):
1312    """
1313    .. versionadded:: 2016.3.0
1314
1315    Retrieve hosts according to the given parameters
1316
1317    .. note::
1318        This function accepts all optional host.get parameters: keyword
1319        argument names differ depending on your zabbix version, see here__.
1320
1321        .. __: https://www.zabbix.com/documentation/2.4/manual/api/reference/host/get
1322
1323    :param host: technical name of the host
1324    :param name: visible name of the host
1325    :param hostids: ids of the hosts
1326    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
1327    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
1328    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
1329
1330
1331    :return: Array with convenient hosts details, False if no host found or on failure.
1332
1333    CLI Example:
1334
1335    .. code-block:: bash
1336
1337        salt '*' zabbix.host_get 'Zabbix server'
1338    """
1339    conn_args = _login(**connection_args)
1340    ret = False
1341    try:
1342        if conn_args:
1343            method = "host.get"
1344            params = {"output": "extend", "filter": {}}
1345            if not name and not hostids and not host:
1346                return False
1347            if name:
1348                params["filter"].setdefault("name", name)
1349            if hostids:
1350                params.setdefault("hostids", hostids)
1351            if host:
1352                params["filter"].setdefault("host", host)
1353            params = _params_extend(params, **connection_args)
1354            ret = _query(method, params, conn_args["url"], conn_args["auth"])
1355            return ret["result"] if len(ret["result"]) > 0 else False
1356        else:
1357            raise KeyError
1358    except KeyError:
1359        return ret
1360
1361
1362def host_update(hostid, **connection_args):
1363    """
1364    .. versionadded:: 2016.3.0
1365
1366    Update existing hosts
1367
1368    .. note::
1369        This function accepts all standard host and host.update properties:
1370        keyword argument names differ depending on your zabbix version, see the
1371        documentation for `host objects`_ and the documentation for `updating
1372        hosts`_.
1373
1374        .. _`host objects`: https://www.zabbix.com/documentation/2.4/manual/api/reference/host/object#host
1375        .. _`updating hosts`: https://www.zabbix.com/documentation/2.4/manual/api/reference/host/update
1376
1377    :param hostid: ID of the host to update
1378    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
1379    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
1380    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
1381    :param visible_name: string with visible name of the host, use
1382        'visible_name' instead of 'name' parameter to not mess with value
1383        supplied from Salt sls file.
1384
1385    :return: ID of the updated host.
1386
1387    CLI Example:
1388
1389    .. code-block:: bash
1390
1391        salt '*' zabbix.host_update 10084 name='Zabbix server2'
1392    """
1393    conn_args = _login(**connection_args)
1394    ret = False
1395    try:
1396        if conn_args:
1397            method = "host.update"
1398            params = {"hostid": hostid}
1399            params = _params_extend(params, _ignore_name=True, **connection_args)
1400            ret = _query(method, params, conn_args["url"], conn_args["auth"])
1401            return ret["result"]["hostids"]
1402        else:
1403            raise KeyError
1404    except KeyError:
1405        return ret
1406
1407
1408def host_inventory_get(hostids, **connection_args):
1409    """
1410    Retrieve host inventory according to the given parameters.
1411    See: https://www.zabbix.com/documentation/2.4/manual/api/reference/host/object#host_inventory
1412
1413    .. versionadded:: 2019.2.0
1414
1415    :param hostids: ID of the host to query
1416    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
1417    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
1418    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
1419
1420    :return: Array with host inventory fields, populated or not, False if host inventory is disabled or on failure.
1421
1422    CLI Example:
1423
1424    .. code-block:: bash
1425
1426        salt '*' zabbix.host_inventory_get 101054
1427    """
1428    conn_args = _login(**connection_args)
1429    ret = False
1430    try:
1431        if conn_args:
1432            method = "host.get"
1433            params = {"selectInventory": "extend"}
1434            if hostids:
1435                params.setdefault("hostids", hostids)
1436            params = _params_extend(params, **connection_args)
1437            ret = _query(method, params, conn_args["url"], conn_args["auth"])
1438            return (
1439                ret["result"][0]["inventory"]
1440                if ret["result"] and ret["result"][0]["inventory"]
1441                else False
1442            )
1443        else:
1444            raise KeyError
1445    except KeyError:
1446        return ret
1447
1448
1449def host_inventory_set(hostid, **connection_args):
1450    """
1451    Update host inventory items
1452    NOTE: This function accepts all standard host: keyword argument names for inventory
1453    see: https://www.zabbix.com/documentation/2.4/manual/api/reference/host/object#host_inventory
1454
1455    .. versionadded:: 2019.2.0
1456
1457    :param hostid: ID of the host to update
1458    :param clear_old: Set to True in order to remove all existing inventory items before setting the specified items
1459    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
1460    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
1461    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
1462
1463    :return: ID of the updated host, False on failure.
1464
1465    CLI Example:
1466
1467    .. code-block:: bash
1468
1469        salt '*' zabbix.host_inventory_set 101054 asset_tag=jml3322 type=vm clear_old=True
1470    """
1471    conn_args = _login(**connection_args)
1472    ret = False
1473    try:
1474        if conn_args:
1475            params = {}
1476            clear_old = False
1477            method = "host.update"
1478
1479            if connection_args.get("clear_old"):
1480                clear_old = True
1481            connection_args.pop("clear_old", None)
1482
1483            inventory_mode = connection_args.pop("inventory_mode", "0")
1484
1485            inventory_params = dict(_params_extend(params, **connection_args))
1486            for key in inventory_params:
1487                params.pop(key, None)
1488
1489            if hostid:
1490                params.setdefault("hostid", hostid)
1491            if clear_old:
1492                # Set inventory to disabled in order to clear existing data
1493                params["inventory_mode"] = "-1"
1494                ret = _query(method, params, conn_args["url"], conn_args["auth"])
1495
1496            # Set inventory mode to manual in order to submit inventory data
1497            params["inventory_mode"] = inventory_mode
1498            params["inventory"] = inventory_params
1499            ret = _query(method, params, conn_args["url"], conn_args["auth"])
1500            return ret["result"]
1501        else:
1502            raise KeyError
1503    except KeyError:
1504        return ret
1505
1506
1507def host_list(**connection_args):
1508    """
1509    Retrieve all hosts.
1510
1511    .. versionadded:: 2016.3.0
1512
1513    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
1514    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
1515    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
1516
1517    :return: Array with details about hosts, False on failure.
1518
1519    CLI Example:
1520
1521    .. code-block:: bash
1522
1523        salt '*' zabbix.host_list
1524    """
1525    conn_args = _login(**connection_args)
1526    ret = False
1527    try:
1528        if conn_args:
1529            method = "host.get"
1530            params = {
1531                "output": "extend",
1532            }
1533            ret = _query(method, params, conn_args["url"], conn_args["auth"])
1534            return ret["result"]
1535        else:
1536            raise KeyError
1537    except KeyError:
1538        return ret
1539
1540
1541def hostgroup_create(name, **connection_args):
1542    """
1543    .. versionadded:: 2016.3.0
1544
1545    Create a host group
1546
1547    .. note::
1548        This function accepts all standard host group properties: keyword
1549        argument names differ depending on your zabbix version, see here__.
1550
1551        .. __: https://www.zabbix.com/documentation/2.4/manual/api/reference/hostgroup/object#host_group
1552
1553    :param name: name of the host group
1554    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
1555    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
1556    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
1557
1558    :return: ID of the created host group.
1559
1560    CLI Example:
1561
1562    .. code-block:: bash
1563
1564        salt '*' zabbix.hostgroup_create MyNewGroup
1565    """
1566    conn_args = _login(**connection_args)
1567    ret = False
1568    try:
1569        if conn_args:
1570            method = "hostgroup.create"
1571            params = {"name": name}
1572            params = _params_extend(params, **connection_args)
1573            ret = _query(method, params, conn_args["url"], conn_args["auth"])
1574            return ret["result"]["groupids"]
1575        else:
1576            raise KeyError
1577    except KeyError:
1578        return ret
1579
1580
1581def hostgroup_delete(hostgroupids, **connection_args):
1582    """
1583    Delete the host group.
1584
1585    .. versionadded:: 2016.3.0
1586
1587    :param hostgroupids: IDs of the host groups to delete
1588    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
1589    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
1590    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
1591
1592    :return: ID of the deleted host groups, False on failure.
1593
1594    CLI Example:
1595
1596    .. code-block:: bash
1597
1598        salt '*' zabbix.hostgroup_delete 23
1599    """
1600    conn_args = _login(**connection_args)
1601    ret = False
1602    try:
1603        if conn_args:
1604            method = "hostgroup.delete"
1605            if not isinstance(hostgroupids, list):
1606                params = [hostgroupids]
1607            else:
1608                params = hostgroupids
1609            ret = _query(method, params, conn_args["url"], conn_args["auth"])
1610            return ret["result"]["groupids"]
1611        else:
1612            raise KeyError
1613    except KeyError:
1614        return ret
1615
1616
1617def hostgroup_exists(
1618    name=None, groupid=None, node=None, nodeids=None, **connection_args
1619):
1620    """
1621    Checks if at least one host group that matches the given filter criteria exists.
1622
1623    .. versionadded:: 2016.3.0
1624
1625    :param name: names of the host groups
1626    :param groupid: host group IDs
1627    :param node: name of the node the host groups must belong to (zabbix API < 2.4)
1628    :param nodeids: IDs of the nodes the host groups must belong to (zabbix API < 2.4)
1629    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
1630    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
1631    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
1632
1633    :return: True if at least one host group exists, False if not or on failure.
1634
1635    CLI Example:
1636
1637    .. code-block:: bash
1638
1639        salt '*' zabbix.hostgroup_exists MyNewGroup
1640    """
1641    conn_args = _login(**connection_args)
1642    zabbix_version = apiinfo_version(**connection_args)
1643    ret = False
1644    try:
1645        if conn_args:
1646            # hostgroup.exists deprecated
1647            if _LooseVersion(zabbix_version) > _LooseVersion("2.5"):
1648                if not groupid:
1649                    groupid = None
1650                if not name:
1651                    name = None
1652                ret = hostgroup_get(name, groupid, **connection_args)
1653                return bool(ret)
1654            # zabbix 2.4 nad earlier
1655            else:
1656                params = {}
1657                method = "hostgroup.exists"
1658                if groupid:
1659                    params["groupid"] = groupid
1660                if name:
1661                    params["name"] = name
1662                # deprecated in 2.4
1663                if _LooseVersion(zabbix_version) < _LooseVersion("2.4"):
1664                    if node:
1665                        params["node"] = node
1666                    if nodeids:
1667                        params["nodeids"] = nodeids
1668                if not groupid and not name and not node and not nodeids:
1669                    return {
1670                        "result": False,
1671                        "comment": (
1672                            "Please submit groupid, name, node or nodeids parameter"
1673                            " tocheck if at least one host group that matches the given"
1674                            " filter criteria exists."
1675                        ),
1676                    }
1677                ret = _query(method, params, conn_args["url"], conn_args["auth"])
1678                return ret["result"]
1679        else:
1680            raise KeyError
1681    except KeyError:
1682        return ret
1683
1684
1685def hostgroup_get(name=None, groupids=None, hostids=None, **connection_args):
1686    """
1687    .. versionadded:: 2016.3.0
1688
1689    Retrieve host groups according to the given parameters
1690
1691    .. note::
1692        This function accepts all standard hostgroup.get properities: keyword
1693        argument names differ depending on your zabbix version, see here__.
1694
1695        .. __: https://www.zabbix.com/documentation/2.2/manual/api/reference/hostgroup/get
1696
1697    :param name: names of the host groups
1698    :param groupid: host group IDs
1699    :param node: name of the node the host groups must belong to
1700    :param nodeids: IDs of the nodes the host groups must belong to
1701    :param hostids: return only host groups that contain the given hosts
1702
1703    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
1704    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
1705    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
1706
1707    :return: Array with host groups details, False if no convenient host group found or on failure.
1708
1709    CLI Example:
1710
1711    .. code-block:: bash
1712
1713        salt '*' zabbix.hostgroup_get MyNewGroup
1714    """
1715    conn_args = _login(**connection_args)
1716    ret = False
1717    try:
1718        if conn_args:
1719            method = "hostgroup.get"
1720            params = {"output": "extend"}
1721            if not groupids and not name and not hostids:
1722                return False
1723            if name:
1724                name_dict = {"name": name}
1725                params.setdefault("filter", name_dict)
1726            if groupids:
1727                params.setdefault("groupids", groupids)
1728            if hostids:
1729                params.setdefault("hostids", hostids)
1730            params = _params_extend(params, **connection_args)
1731            ret = _query(method, params, conn_args["url"], conn_args["auth"])
1732            return ret["result"] if len(ret["result"]) > 0 else False
1733        else:
1734            raise KeyError
1735    except KeyError:
1736        return ret
1737
1738
1739def hostgroup_update(groupid, name=None, **connection_args):
1740    """
1741    .. versionadded:: 2016.3.0
1742
1743    Update existing hosts group
1744
1745    .. note::
1746        This function accepts all standard host group properties: keyword
1747        argument names differ depending on your zabbix version, see here__.
1748
1749        .. __: https://www.zabbix.com/documentation/2.4/manual/api/reference/hostgroup/object#host_group
1750
1751    :param groupid: ID of the host group to update
1752    :param name: name of the host group
1753    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
1754    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
1755    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
1756
1757    :return: IDs of updated host groups.
1758
1759    CLI Example:
1760
1761    .. code-block:: bash
1762
1763        salt '*' zabbix.hostgroup_update 24 name='Renamed Name'
1764    """
1765    conn_args = _login(**connection_args)
1766    ret = False
1767    try:
1768        if conn_args:
1769            method = "hostgroup.update"
1770            params = {"groupid": groupid}
1771            if name:
1772                params["name"] = name
1773            params = _params_extend(params, **connection_args)
1774            ret = _query(method, params, conn_args["url"], conn_args["auth"])
1775            return ret["result"]["groupids"]
1776        else:
1777            raise KeyError
1778    except KeyError:
1779        return ret
1780
1781
1782def hostgroup_list(**connection_args):
1783    """
1784    Retrieve all host groups.
1785
1786    .. versionadded:: 2016.3.0
1787
1788    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
1789    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
1790    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
1791
1792    :return: Array with details about host groups, False on failure.
1793
1794    CLI Example:
1795
1796    .. code-block:: bash
1797
1798        salt '*' zabbix.hostgroup_list
1799    """
1800    conn_args = _login(**connection_args)
1801    ret = False
1802    try:
1803        if conn_args:
1804            method = "hostgroup.get"
1805            params = {
1806                "output": "extend",
1807            }
1808            ret = _query(method, params, conn_args["url"], conn_args["auth"])
1809            return ret["result"]
1810        else:
1811            raise KeyError
1812    except KeyError:
1813        return ret
1814
1815
1816def hostinterface_get(hostids, **connection_args):
1817    """
1818    .. versionadded:: 2016.3.0
1819
1820    Retrieve host groups according to the given parameters
1821
1822    .. note::
1823        This function accepts all standard hostinterface.get properities:
1824        keyword argument names differ depending on your zabbix version, see
1825        here__.
1826
1827        .. __: https://www.zabbix.com/documentation/2.4/manual/api/reference/hostinterface/get
1828
1829    :param hostids: Return only host interfaces used by the given hosts.
1830
1831    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
1832
1833    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
1834
1835    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
1836
1837    :return: Array with host interfaces details, False if no convenient host interfaces found or on failure.
1838
1839    CLI Example:
1840
1841    .. code-block:: bash
1842
1843        salt '*' zabbix.hostinterface_get 101054
1844    """
1845    conn_args = _login(**connection_args)
1846    ret = False
1847    try:
1848        if conn_args:
1849            method = "hostinterface.get"
1850            params = {"output": "extend"}
1851            if hostids:
1852                params.setdefault("hostids", hostids)
1853            params = _params_extend(params, **connection_args)
1854            ret = _query(method, params, conn_args["url"], conn_args["auth"])
1855            return ret["result"] if len(ret["result"]) > 0 else False
1856        else:
1857            raise KeyError
1858    except KeyError:
1859        return ret
1860
1861
1862def hostinterface_create(
1863    hostid, ip_, dns="", main=1, if_type=1, useip=1, port=None, **connection_args
1864):
1865    """
1866    .. versionadded:: 2016.3.0
1867
1868    Create new host interface
1869
1870    .. note::
1871        This function accepts all standard host group interface: keyword
1872        argument names differ depending on your zabbix version, see here__.
1873
1874        .. __: https://www.zabbix.com/documentation/3.0/manual/api/reference/hostinterface/object
1875
1876    :param hostid: ID of the host the interface belongs to
1877
1878    :param ip_: IP address used by the interface
1879
1880    :param dns: DNS name used by the interface
1881
1882    :param main: whether the interface is used as default on the host (0 - not default, 1 - default)
1883
1884    :param port: port number used by the interface
1885
1886    :param type: Interface type (1 - agent; 2 - SNMP; 3 - IPMI; 4 - JMX)
1887
1888    :param useip: Whether the connection should be made via IP (0 - connect
1889        using host DNS name; 1 - connect using host IP address for this host
1890        interface)
1891
1892    :param _connection_user: Optional - zabbix user (can also be set in opts or
1893        pillar, see module's docstring)
1894
1895    :param _connection_password: Optional - zabbix password (can also be set in
1896        opts or pillar, see module's docstring)
1897
1898    :param _connection_url: Optional - url of zabbix frontend (can also be set
1899        in opts, pillar, see module's docstring)
1900
1901    :return: ID of the created host interface, False on failure.
1902
1903    CLI Example:
1904
1905    .. code-block:: bash
1906
1907        salt '*' zabbix.hostinterface_create 10105 192.193.194.197
1908    """
1909    conn_args = _login(**connection_args)
1910    ret = False
1911
1912    if not port:
1913        port = INTERFACE_DEFAULT_PORTS[if_type]
1914
1915    try:
1916        if conn_args:
1917            method = "hostinterface.create"
1918            params = {
1919                "hostid": hostid,
1920                "ip": ip_,
1921                "dns": dns,
1922                "main": main,
1923                "port": port,
1924                "type": if_type,
1925                "useip": useip,
1926            }
1927            params = _params_extend(params, **connection_args)
1928            ret = _query(method, params, conn_args["url"], conn_args["auth"])
1929            return ret["result"]["interfaceids"]
1930        else:
1931            raise KeyError
1932    except KeyError:
1933        return ret
1934
1935
1936def hostinterface_delete(interfaceids, **connection_args):
1937    """
1938    Delete host interface
1939
1940    .. versionadded:: 2016.3.0
1941
1942    :param interfaceids: IDs of the host interfaces to delete
1943    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
1944    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
1945    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
1946
1947    :return: ID of deleted host interfaces, False on failure.
1948
1949    CLI Example:
1950
1951    .. code-block:: bash
1952
1953        salt '*' zabbix.hostinterface_delete 50
1954    """
1955    conn_args = _login(**connection_args)
1956    ret = False
1957    try:
1958        if conn_args:
1959            method = "hostinterface.delete"
1960            if isinstance(interfaceids, list):
1961                params = interfaceids
1962            else:
1963                params = [interfaceids]
1964            ret = _query(method, params, conn_args["url"], conn_args["auth"])
1965            return ret["result"]["interfaceids"]
1966        else:
1967            raise KeyError
1968    except KeyError:
1969        return ret
1970
1971
1972def hostinterface_update(interfaceid, **connection_args):
1973    """
1974    .. versionadded:: 2016.3.0
1975
1976    Update host interface
1977
1978    .. note::
1979        This function accepts all standard hostinterface: keyword argument
1980        names differ depending on your zabbix version, see here__.
1981
1982        .. __: https://www.zabbix.com/documentation/2.4/manual/api/reference/hostinterface/object#host_interface
1983
1984    :param interfaceid: ID of the hostinterface to update
1985
1986    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
1987
1988    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
1989
1990    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
1991
1992    :return: ID of the updated host interface, False on failure.
1993
1994    CLI Example:
1995
1996    .. code-block:: bash
1997
1998        salt '*' zabbix.hostinterface_update 6 ip_=0.0.0.2
1999    """
2000    conn_args = _login(**connection_args)
2001    ret = False
2002    try:
2003        if conn_args:
2004            method = "hostinterface.update"
2005            params = {"interfaceid": interfaceid}
2006            params = _params_extend(params, **connection_args)
2007            ret = _query(method, params, conn_args["url"], conn_args["auth"])
2008            return ret["result"]["interfaceids"]
2009        else:
2010            raise KeyError
2011    except KeyError:
2012        return ret
2013
2014
2015def usermacro_get(
2016    macro=None,
2017    hostids=None,
2018    templateids=None,
2019    hostmacroids=None,
2020    globalmacroids=None,
2021    globalmacro=False,
2022    **connection_args
2023):
2024    """
2025    Retrieve user macros according to the given parameters.
2026
2027    Args:
2028        macro:          name of the usermacro
2029        hostids:        Return macros for the given hostids
2030        templateids:    Return macros for the given templateids
2031        hostmacroids:   Return macros with the given hostmacroids
2032        globalmacroids: Return macros with the given globalmacroids (implies globalmacro=True)
2033        globalmacro:    if True, returns only global macros
2034
2035
2036        optional connection_args:
2037                _connection_user: zabbix user (can also be set in opts or pillar, see module's docstring)
2038                _connection_password: zabbix password (can also be set in opts or pillar, see module's docstring)
2039                _connection_url: url of zabbix frontend (can also be set in opts or pillar, see module's docstring)
2040
2041    Returns:
2042        Array with usermacro details, False if no usermacro found or on failure.
2043
2044    CLI Example:
2045
2046    .. code-block:: bash
2047
2048        salt '*' zabbix.usermacro_get macro='{$SNMP_COMMUNITY}'
2049    """
2050    conn_args = _login(**connection_args)
2051    ret = False
2052    try:
2053        if conn_args:
2054            method = "usermacro.get"
2055            params = {"output": "extend", "filter": {}}
2056            if macro:
2057                # Python mistakenly interprets macro names starting and ending with '{' and '}' as a dict
2058                if isinstance(macro, dict):
2059                    macro = "{" + str(next(iter(macro))) + "}"
2060                if not macro.startswith("{") and not macro.endswith("}"):
2061                    macro = "{" + macro + "}"
2062                params["filter"].setdefault("macro", macro)
2063            if hostids:
2064                params.setdefault("hostids", hostids)
2065            elif templateids:
2066                params.setdefault("templateids", hostids)
2067            if hostmacroids:
2068                params.setdefault("hostmacroids", hostmacroids)
2069            elif globalmacroids:
2070                globalmacro = True
2071                params.setdefault("globalmacroids", globalmacroids)
2072            if globalmacro:
2073                params = _params_extend(params, globalmacro=True)
2074            params = _params_extend(params, **connection_args)
2075            ret = _query(method, params, conn_args["url"], conn_args["auth"])
2076            return ret["result"] if len(ret["result"]) > 0 else False
2077        else:
2078            raise KeyError
2079    except KeyError:
2080        return ret
2081
2082
2083def usermacro_create(macro, value, hostid, **connection_args):
2084    """
2085    Create new host usermacro.
2086
2087    :param macro: name of the host usermacro
2088    :param value: value of the host usermacro
2089    :param hostid: hostid or templateid
2090    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
2091    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
2092    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
2093
2094    return: ID of the created host usermacro.
2095
2096    CLI Example:
2097
2098    .. code-block:: bash
2099
2100        salt '*' zabbix.usermacro_create '{$SNMP_COMMUNITY}' 'public' 1
2101    """
2102    conn_args = _login(**connection_args)
2103    ret = False
2104    try:
2105        if conn_args:
2106            params = {}
2107            method = "usermacro.create"
2108            if macro:
2109                # Python mistakenly interprets macro names starting and ending with '{' and '}' as a dict
2110                if isinstance(macro, dict):
2111                    macro = "{" + str(next(iter(macro))) + "}"
2112                if not macro.startswith("{") and not macro.endswith("}"):
2113                    macro = "{" + macro + "}"
2114                params["macro"] = macro
2115            params["value"] = value
2116            params["hostid"] = hostid
2117            params = _params_extend(params, _ignore_name=True, **connection_args)
2118            ret = _query(method, params, conn_args["url"], conn_args["auth"])
2119            return ret["result"]["hostmacroids"][0]
2120        else:
2121            raise KeyError
2122    except KeyError:
2123        return ret
2124
2125
2126def usermacro_createglobal(macro, value, **connection_args):
2127    """
2128    Create new global usermacro.
2129
2130    :param macro: name of the global usermacro
2131    :param value: value of the global usermacro
2132    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
2133    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
2134    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
2135
2136    return: ID of the created global usermacro.
2137
2138    CLI Example:
2139
2140    .. code-block:: bash
2141
2142        salt '*' zabbix.usermacro_createglobal '{$SNMP_COMMUNITY}' 'public'
2143    """
2144    conn_args = _login(**connection_args)
2145    ret = False
2146    try:
2147        if conn_args:
2148            params = {}
2149            method = "usermacro.createglobal"
2150            if macro:
2151                # Python mistakenly interprets macro names starting and ending with '{' and '}' as a dict
2152                if isinstance(macro, dict):
2153                    macro = "{" + str(next(iter(macro))) + "}"
2154                if not macro.startswith("{") and not macro.endswith("}"):
2155                    macro = "{" + macro + "}"
2156                params["macro"] = macro
2157            params["value"] = value
2158            params = _params_extend(params, _ignore_name=True, **connection_args)
2159            ret = _query(method, params, conn_args["url"], conn_args["auth"])
2160            return ret["result"]["globalmacroids"][0]
2161        else:
2162            raise KeyError
2163    except KeyError:
2164        return ret
2165
2166
2167def usermacro_delete(macroids, **connection_args):
2168    """
2169    Delete host usermacros.
2170
2171    :param macroids: macroids of the host usermacros
2172
2173    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
2174    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
2175    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
2176
2177    return: IDs of the deleted host usermacro.
2178
2179    CLI Example:
2180
2181    .. code-block:: bash
2182
2183        salt '*' zabbix.usermacro_delete 21
2184    """
2185    conn_args = _login(**connection_args)
2186    ret = False
2187    try:
2188        if conn_args:
2189            method = "usermacro.delete"
2190            if isinstance(macroids, list):
2191                params = macroids
2192            else:
2193                params = [macroids]
2194            ret = _query(method, params, conn_args["url"], conn_args["auth"])
2195            return ret["result"]["hostmacroids"]
2196        else:
2197            raise KeyError
2198    except KeyError:
2199        return ret
2200
2201
2202def usermacro_deleteglobal(macroids, **connection_args):
2203    """
2204    Delete global usermacros.
2205
2206    :param macroids: macroids of the global usermacros
2207
2208    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
2209    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
2210    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
2211
2212    return: IDs of the deleted global usermacro.
2213
2214    CLI Example:
2215
2216    .. code-block:: bash
2217
2218        salt '*' zabbix.usermacro_deleteglobal 21
2219    """
2220    conn_args = _login(**connection_args)
2221    ret = False
2222    try:
2223        if conn_args:
2224            method = "usermacro.deleteglobal"
2225            if isinstance(macroids, list):
2226                params = macroids
2227            else:
2228                params = [macroids]
2229            ret = _query(method, params, conn_args["url"], conn_args["auth"])
2230            return ret["result"]["globalmacroids"]
2231        else:
2232            raise KeyError
2233    except KeyError:
2234        return ret
2235
2236
2237def usermacro_update(hostmacroid, value, **connection_args):
2238    """
2239    Update existing host usermacro.
2240
2241    :param hostmacroid: id of the host usermacro
2242    :param value: new value of the host usermacro
2243    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
2244    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
2245    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
2246
2247    return: ID of the update host usermacro.
2248
2249    CLI Example:
2250
2251    .. code-block:: bash
2252
2253        salt '*' zabbix.usermacro_update 1 'public'
2254    """
2255    conn_args = _login(**connection_args)
2256    ret = False
2257    try:
2258        if conn_args:
2259            params = {}
2260            method = "usermacro.update"
2261            params["hostmacroid"] = hostmacroid
2262            params["value"] = value
2263            params = _params_extend(params, _ignore_name=True, **connection_args)
2264            ret = _query(method, params, conn_args["url"], conn_args["auth"])
2265            return ret["result"]["hostmacroids"][0]
2266        else:
2267            raise KeyError
2268    except KeyError:
2269        return ret
2270
2271
2272def usermacro_updateglobal(globalmacroid, value, **connection_args):
2273    """
2274    Update existing global usermacro.
2275
2276    :param globalmacroid: id of the host usermacro
2277    :param value: new value of the host usermacro
2278    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
2279    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
2280    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
2281
2282    return: ID of the update global usermacro.
2283
2284    CLI Example:
2285
2286    .. code-block:: bash
2287
2288        salt '*' zabbix.usermacro_updateglobal 1 'public'
2289    """
2290    conn_args = _login(**connection_args)
2291    ret = False
2292    try:
2293        if conn_args:
2294            params = {}
2295            method = "usermacro.updateglobal"
2296            params["globalmacroid"] = globalmacroid
2297            params["value"] = value
2298            params = _params_extend(params, _ignore_name=True, **connection_args)
2299            ret = _query(method, params, conn_args["url"], conn_args["auth"])
2300            return ret["result"]["globalmacroids"][0]
2301        else:
2302            raise KeyError
2303    except KeyError:
2304        return ret
2305
2306
2307def mediatype_get(name=None, mediatypeids=None, **connection_args):
2308    """
2309    Retrieve mediatypes according to the given parameters.
2310
2311    Args:
2312        name:         Name or description of the mediatype
2313        mediatypeids: ids of the mediatypes
2314
2315        optional connection_args:
2316                _connection_user: zabbix user (can also be set in opts or pillar, see module's docstring)
2317                _connection_password: zabbix password (can also be set in opts or pillar, see module's docstring)
2318                _connection_url: url of zabbix frontend (can also be set in opts or pillar, see module's docstring)
2319
2320                all optional mediatype.get parameters: keyword argument names depends on your zabbix version, see:
2321
2322                https://www.zabbix.com/documentation/2.2/manual/api/reference/mediatype/get
2323
2324    Returns:
2325        Array with mediatype details, False if no mediatype found or on failure.
2326
2327    CLI Example:
2328
2329    .. code-block:: bash
2330
2331        salt '*' zabbix.mediatype_get name='Email'
2332        salt '*' zabbix.mediatype_get mediatypeids="['1', '2', '3']"
2333    """
2334    conn_args = _login(**connection_args)
2335    zabbix_version = apiinfo_version(**connection_args)
2336    ret = False
2337    try:
2338        if conn_args:
2339            method = "mediatype.get"
2340            params = {"output": "extend", "filter": {}}
2341            if name:
2342                # since zabbix API 4.4, mediatype has new attribute: name
2343                if _LooseVersion(zabbix_version) >= _LooseVersion("4.4"):
2344                    params["filter"].setdefault("name", name)
2345                else:
2346                    params["filter"].setdefault("description", name)
2347            if mediatypeids:
2348                params.setdefault("mediatypeids", mediatypeids)
2349            params = _params_extend(params, **connection_args)
2350            ret = _query(method, params, conn_args["url"], conn_args["auth"])
2351            return ret["result"] if len(ret["result"]) > 0 else False
2352        else:
2353            raise KeyError
2354    except KeyError:
2355        return ret
2356
2357
2358def mediatype_create(name, mediatype, **connection_args):
2359    """
2360    Create new mediatype
2361
2362    .. note::
2363        This function accepts all standard mediatype properties: keyword
2364        argument names differ depending on your zabbix version, see here__.
2365
2366        .. __: https://www.zabbix.com/documentation/3.0/manual/api/reference/mediatype/object
2367
2368    :param mediatype: media type - 0: email, 1: script, 2: sms, 3: Jabber, 100: Ez Texting
2369    :param exec_path: exec path - Required for script and Ez Texting types, see Zabbix API docs
2370    :param gsm_modem: exec path - Required for sms type, see Zabbix API docs
2371    :param smtp_email: email address from which notifications will be sent, required for email type
2372    :param smtp_helo: SMTP HELO, required for email type
2373    :param smtp_server: SMTP server, required for email type
2374    :param status: whether the media type is enabled - 0: enabled, 1: disabled
2375    :param username: authentication user, required for Jabber and Ez Texting types
2376    :param passwd: authentication password, required for Jabber and Ez Texting types
2377    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
2378    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
2379    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
2380
2381    return: ID of the created mediatype.
2382
2383    CLI Example:
2384
2385    .. code-block:: bash
2386
2387        salt '*' zabbix.mediatype_create 'Email' 0 smtp_email='noreply@example.com'
2388        smtp_server='mailserver.example.com' smtp_helo='zabbix.example.com'
2389    """
2390    conn_args = _login(**connection_args)
2391    zabbix_version = apiinfo_version(**connection_args)
2392    ret = False
2393    try:
2394        if conn_args:
2395            method = "mediatype.create"
2396            # since zabbix 4.4 api, mediatype has new attribute: name
2397            if _LooseVersion(zabbix_version) >= _LooseVersion("4.4"):
2398                params = {"name": name}
2399                _ignore_name = False
2400            else:
2401                params = {"description": name}
2402                _ignore_name = True
2403            params["type"] = mediatype
2404            params = _params_extend(params, _ignore_name, **connection_args)
2405            ret = _query(method, params, conn_args["url"], conn_args["auth"])
2406            return ret["result"]["mediatypeid"]
2407        else:
2408            raise KeyError
2409    except KeyError:
2410        return ret
2411
2412
2413def mediatype_delete(mediatypeids, **connection_args):
2414    """
2415    Delete mediatype
2416
2417
2418    :param interfaceids: IDs of the mediatypes to delete
2419    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
2420    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
2421    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
2422
2423    :return: ID of deleted mediatype, False on failure.
2424
2425    CLI Example:
2426
2427    .. code-block:: bash
2428
2429        salt '*' zabbix.mediatype_delete 3
2430    """
2431    conn_args = _login(**connection_args)
2432    ret = False
2433    try:
2434        if conn_args:
2435            method = "mediatype.delete"
2436            if isinstance(mediatypeids, list):
2437                params = mediatypeids
2438            else:
2439                params = [mediatypeids]
2440            ret = _query(method, params, conn_args["url"], conn_args["auth"])
2441            return ret["result"]["mediatypeids"]
2442        else:
2443            raise KeyError
2444    except KeyError:
2445        return ret
2446
2447
2448def mediatype_update(mediatypeid, name=False, mediatype=False, **connection_args):
2449    """
2450    Update existing mediatype
2451
2452    .. note::
2453        This function accepts all standard mediatype properties: keyword
2454        argument names differ depending on your zabbix version, see here__.
2455
2456        .. __: https://www.zabbix.com/documentation/3.0/manual/api/reference/mediatype/object
2457
2458    :param mediatypeid: ID of the mediatype to update
2459    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
2460    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
2461    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
2462
2463    :return: IDs of the updated mediatypes, False on failure.
2464
2465    CLI Example:
2466
2467    .. code-block:: bash
2468
2469        salt '*' zabbix.usergroup_update 8 name="Email update"
2470    """
2471    conn_args = _login(**connection_args)
2472    ret = False
2473    try:
2474        if conn_args:
2475            method = "mediatype.update"
2476            params = {"mediatypeid": mediatypeid}
2477            if name:
2478                params["description"] = name
2479            if mediatype:
2480                params["type"] = mediatype
2481            params = _params_extend(params, **connection_args)
2482            ret = _query(method, params, conn_args["url"], conn_args["auth"])
2483            return ret["result"]["mediatypeids"]
2484        else:
2485            raise KeyError
2486    except KeyError:
2487        return ret
2488
2489
2490def template_get(name=None, host=None, templateids=None, **connection_args):
2491    """
2492    Retrieve templates according to the given parameters.
2493
2494    Args:
2495        host: technical name of the template
2496        name: visible name of the template
2497        hostids: ids of the templates
2498
2499        optional connection_args:
2500                _connection_user: zabbix user (can also be set in opts or pillar, see module's docstring)
2501                _connection_password: zabbix password (can also be set in opts or pillar, see module's docstring)
2502                _connection_url: url of zabbix frontend (can also be set in opts or pillar, see module's docstring)
2503
2504                all optional template.get parameters: keyword argument names depends on your zabbix version, see:
2505
2506                https://www.zabbix.com/documentation/2.4/manual/api/reference/template/get
2507
2508    Returns:
2509        Array with convenient template details, False if no template found or on failure.
2510
2511    CLI Example:
2512
2513    .. code-block:: bash
2514
2515        salt '*' zabbix.template_get name='Template OS Linux'
2516        salt '*' zabbix.template_get templateids="['10050', '10001']"
2517    """
2518    conn_args = _login(**connection_args)
2519    ret = False
2520    try:
2521        if conn_args:
2522            method = "template.get"
2523            params = {"output": "extend", "filter": {}}
2524            if name:
2525                params["filter"].setdefault("name", name)
2526            if host:
2527                params["filter"].setdefault("host", host)
2528            if templateids:
2529                params.setdefault("templateids", templateids)
2530            params = _params_extend(params, **connection_args)
2531            ret = _query(method, params, conn_args["url"], conn_args["auth"])
2532            return ret["result"] if len(ret["result"]) > 0 else False
2533        else:
2534            raise KeyError
2535    except KeyError:
2536        return ret
2537
2538
2539def run_query(method, params, **connection_args):
2540    """
2541    Send Zabbix API call
2542
2543    Args:
2544        method: actual operation to perform via the API
2545        params: parameters required for specific method
2546
2547        optional connection_args:
2548                _connection_user: zabbix user (can also be set in opts or pillar, see module's docstring)
2549                _connection_password: zabbix password (can also be set in opts or pillar, see module's docstring)
2550                _connection_url: url of zabbix frontend (can also be set in opts or pillar, see module's docstring)
2551
2552                all optional template.get parameters: keyword argument names depends on your zabbix version, see:
2553
2554                https://www.zabbix.com/documentation/2.4/manual/api/reference/
2555
2556    Returns:
2557        Response from Zabbix API
2558
2559    CLI Example:
2560
2561    .. code-block:: bash
2562
2563        salt '*' zabbix.run_query proxy.create '{"host": "zabbixproxy.domain.com", "status": "5"}'
2564    """
2565    conn_args = _login(**connection_args)
2566    ret = False
2567    try:
2568        if conn_args:
2569            params = _params_extend(params, **connection_args)
2570            ret = _query(method, params, conn_args["url"], conn_args["auth"])
2571            if isinstance(ret["result"], bool):
2572                return ret["result"]
2573            if ret["result"] is True or len(ret["result"]) > 0:
2574                return ret["result"]
2575            else:
2576                return False
2577        else:
2578            raise KeyError
2579    except KeyError:
2580        return ret
2581
2582
2583def configuration_import(config_file, rules=None, file_format="xml", **connection_args):
2584    """
2585    .. versionadded:: 2017.7
2586
2587    Imports Zabbix configuration specified in file to Zabbix server.
2588
2589    :param config_file: File with Zabbix config (local or remote)
2590    :param rules: Optional - Rules that have to be different from default (defaults are the same as in Zabbix web UI.)
2591    :param file_format: Config file format (default: xml)
2592    :param _connection_user: Optional - zabbix user (can also be set in opts or pillar, see module's docstring)
2593    :param _connection_password: Optional - zabbix password (can also be set in opts or pillar, see module's docstring)
2594    :param _connection_url: Optional - url of zabbix frontend (can also be set in opts, pillar, see module's docstring)
2595
2596    CLI Example:
2597
2598    .. code-block:: bash
2599
2600        salt '*' zabbix.configuration_import salt://zabbix/config/zabbix_templates.xml \
2601        "{'screens': {'createMissing': True, 'updateExisting': True}}"
2602    """
2603    zabbix_version = apiinfo_version(**connection_args)
2604
2605    if rules is None:
2606        rules = {}
2607    default_rules = {
2608        "discoveryRules": {
2609            "createMissing": True,
2610            "updateExisting": True,
2611            "deleteMissing": False,
2612        },
2613        "graphs": {
2614            "createMissing": True,
2615            "updateExisting": True,
2616            "deleteMissing": False,
2617        },
2618        "groups": {"createMissing": True},
2619        "hosts": {"createMissing": False, "updateExisting": False},
2620        "images": {"createMissing": False, "updateExisting": False},
2621        "items": {
2622            "createMissing": True,
2623            "updateExisting": True,
2624            "deleteMissing": False,
2625        },
2626        "maps": {"createMissing": False, "updateExisting": False},
2627        "screens": {"createMissing": False, "updateExisting": False},
2628        "templateLinkage": {"createMissing": True},
2629        "templates": {"createMissing": True, "updateExisting": True},
2630        "templateScreens": {
2631            "createMissing": True,
2632            "updateExisting": True,
2633            "deleteMissing": False,
2634        },
2635        "triggers": {
2636            "createMissing": True,
2637            "updateExisting": True,
2638            "deleteMissing": False,
2639        },
2640        "valueMaps": {"createMissing": True, "updateExisting": False},
2641    }
2642    if _LooseVersion(zabbix_version) >= _LooseVersion("3.2"):
2643        # rules/httptests added
2644        default_rules["httptests"] = {
2645            "createMissing": True,
2646            "updateExisting": True,
2647            "deleteMissing": False,
2648        }
2649    if _LooseVersion(zabbix_version) >= _LooseVersion("3.4"):
2650        # rules/applications/upateExisting deprecated
2651        default_rules["applications"] = {"createMissing": True, "deleteMissing": False}
2652    else:
2653        default_rules["applications"] = {
2654            "createMissing": True,
2655            "updateExisting": True,
2656            "deleteMissing": False,
2657        }
2658    new_rules = dict(default_rules)
2659
2660    if rules:
2661        for rule in rules:
2662            if rule in new_rules:
2663                new_rules[rule].update(rules[rule])
2664            else:
2665                new_rules[rule] = rules[rule]
2666    if "salt://" in config_file:
2667        tmpfile = salt.utils.files.mkstemp()
2668        cfile = __salt__["cp.get_file"](config_file, tmpfile)
2669        if not cfile or os.path.getsize(cfile) == 0:
2670            return {
2671                "name": config_file,
2672                "result": False,
2673                "message": "Failed to fetch config file.",
2674            }
2675    else:
2676        cfile = config_file
2677        if not os.path.isfile(cfile):
2678            return {
2679                "name": config_file,
2680                "result": False,
2681                "message": "Invalid file path.",
2682            }
2683
2684    with salt.utils.files.fopen(cfile, mode="r") as fp_:
2685        xml = fp_.read()
2686
2687    if "salt://" in config_file:
2688        salt.utils.files.safe_rm(cfile)
2689
2690    params = {"format": file_format, "rules": new_rules, "source": xml}
2691    log.info("CONFIGURATION IMPORT: rules: %s", str(params["rules"]))
2692    try:
2693        run_query("configuration.import", params, **connection_args)
2694        return {
2695            "name": config_file,
2696            "result": True,
2697            "message": 'Zabbix API "configuration.import" method called successfully.',
2698        }
2699    except SaltException as exc:
2700        return {"name": config_file, "result": False, "message": str(exc)}
2701