#!/usr/local/bin/python3.9
#
# Python script to send incidents from Zabbix to PagerDuty.
#
# Copyright (c) 2013-2014, PagerDuty, Inc. <info@pagerduty.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#   * Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
#   * Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#   * Neither the name of the copyright holder nor the
#     names of its contributors may be used to endorse or promote products
#     derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#

# Parse the Zabbix message body. The body MUST be in this format:
#
# name:{TRIGGER.NAME}
# id:{TRIGGER.ID}
# status:{TRIGGER.STATUS}
# hostname:{HOSTNAME}
# ip:{IPADDRESS}
# value:{TRIGGER.VALUE}
# event_id:{EVENT.ID}
# severity:{TRIGGER.SEVERITY}
#


def _parse_zabbix_body(body_str):
    body = {}
    key, val = (None, None)
    for line in body_str.strip().split('\n'):
        keyval = line.strip().split(':', 1)
        if len(keyval) == 2:
            key, val = keyval
            body[key] = val
        elif key is not None:
            # Treat as continuation of previous line
            body[key] += keyval[0]
        else:
            body[keyval[0]] = keyval[0]
    return body

# Parse the Zabbix message subject.
# The subject MUST be one of the following:
#
# trigger
# resolve
#


def _parse_zabbix_subject(subject_str):
    return subject_str


def main():
    import sys
    from pdagent.pdagentutil import queue_event
    from pdagent.config import load_agent_config

    # The first argument is the service key
    service_key = sys.argv[1]

    # The second argument is the message type
    message_type = _parse_zabbix_subject(sys.argv[2])

    # The third argument is the data
    details = _parse_zabbix_body(sys.argv[3])

    # Zabbix issues a "trigger" with a "NOTE: Escalation cancelled" in details if the host,
    # trigger, or action gets disabled.
    # https://www.zabbix.com/documentation/3.2/manual/config/notifications/action/escalations
    # Convert that into a "resolve" to actually resolve the issue in PagerDuty
    if message_type == "trigger" and "NOTE" in details and "Escalation cancelled" in details["NOTE"]:
        message_type = "resolve"
        details["NOTE"] = details["NOTE"] + \
            " (converted from trigger to resolve by pdagent integration)"

    # Incident key is created by concatenating trigger id and host name.
    # Remember, incident key is used for de-duping and also to match trigger with resolve messages
    incident_key = "%s-%s" % (details["id"], details["hostname"])
    if "incident_key" in details and details["incident_key"]:
        incident_key = details["incident_key"]
    # The description that is rendered in PagerDuty and also sent as SMS and phone alert
    description = "%s : %s for %s" % (
        details["name"], details["status"], details["hostname"])

    # Client URL is an optional property "url" in the Zabbix message
    client = ""
    url = details.get('url', '')
    if url:
        client = "Zabbix"

    agent_config = load_agent_config()
    queue_event(
        agent_config.get_enqueuer(),
        message_type, service_key, incident_key, description, client, url, details,
        agent_config.get_agent_id(), "pd-zabbix",)


if __name__ == "__main__":
    try:
        import pdagent.config
    except ImportError:
        # Fix up for dev layout
        import sys
        from os.path import realpath, dirname
        sys.path.append(dirname(dirname(realpath(__file__))))
        import pdagent.config
    main()
