#!/usr/bin/python
# -*- encoding: utf-8; py-indent-offset: 4 -*-
# +------------------------------------------------------------------+
# |             ____ _               _        __  __ _  __           |
# |            / ___| |__   ___  ___| | __   |  \/  | |/ /           |
# |           | |   | '_ \ / _ \/ __| |/ /   | |\/| | ' /            |
# |           | |___| | | |  __/ (__|   <    | |  | | . \            |
# |            \____|_| |_|\___|\___|_|\_\___|_|  |_|_|\_\           |
# |                                                                  |
# | Copyright Mathias Kettner 2014             mk@mathias-kettner.de |
# +------------------------------------------------------------------+
#
# This file is part of Check_MK.
# The official homepage is at http://mathias-kettner.de/check_mk.
#
# check_mk is free software;  you can redistribute it and/or modify it
# under the  terms of the  GNU General Public License  as published by
# the Free Software Foundation in version 2.  check_mk is  distributed
# in the hope that it will be useful, but WITHOUT ANY WARRANTY;  with-
# out even the implied warranty of  MERCHANTABILITY  or  FITNESS FOR A
# PARTICULAR PURPOSE. See the  GNU General Public License for more de-
# ails.  You should have  received  a copy of the  GNU  General Public
# License along with GNU Make; see the file  COPYING.  If  not,  write
# to the Free Software Foundation, Inc., 51 Franklin St,  Fifth Floor,
# Boston, MA 02110-1301 USA.


# Good docs:
# http://www.cisco.com/en/US/tech/tk648/tk362/technologies_tech_note09186a0080094a91.shtml
#.1.3.6.1.4.1.9.9.106.1.1.1.0 5
# cHsrpGrpTable
###########################
#.1.3.6.1.4.1.9.9.106.1.2.1.1.2.1.192  "HSRP Secret key here"
#.1.3.6.1.4.1.9.9.106.1.2.1.1.2.7.193  "HSRP Secret key here"
#.1.3.6.1.4.1.9.9.106.1.2.1.1.3.1.192  100
#.1.3.6.1.4.1.9.9.106.1.2.1.1.3.7.193  100
#.1.3.6.1.4.1.9.9.106.1.2.1.1.4.1.192  1
#.1.3.6.1.4.1.9.9.106.1.2.1.1.4.7.193  1
#.1.3.6.1.4.1.9.9.106.1.2.1.1.5.1.192  300
#.1.3.6.1.4.1.9.9.106.1.2.1.1.5.7.193  300
#.1.3.6.1.4.1.9.9.106.1.2.1.1.6.1.192  2
#.1.3.6.1.4.1.9.9.106.1.2.1.1.6.7.193  2
#.1.3.6.1.4.1.9.9.106.1.2.1.1.7.1.192  0
#.1.3.6.1.4.1.9.9.106.1.2.1.1.7.7.193  0
#.1.3.6.1.4.1.9.9.106.1.2.1.1.8.1.192  0
#.1.3.6.1.4.1.9.9.106.1.2.1.1.8.7.193  0
#.1.3.6.1.4.1.9.9.106.1.2.1.1.9.1.192  3000
#.1.3.6.1.4.1.9.9.106.1.2.1.1.9.7.193  3000
#.1.3.6.1.4.1.9.9.106.1.2.1.1.10.1.192  10000
#.1.3.6.1.4.1.9.9.106.1.2.1.1.10.7.193  10000
#.1.3.6.1.4.1.9.9.106.1.2.1.1.11.1.192  192.168.10.4
#.1.3.6.1.4.1.9.9.106.1.2.1.1.11.7.193  172.20.10.20 <- hsrp ip
#.1.3.6.1.4.1.9.9.106.1.2.1.1.12.1.192  1
#.1.3.6.1.4.1.9.9.106.1.2.1.1.12.7.193  1
# HSRP Monitored IP interfaces. If any of those go down, the priority of
# the router will be lowered.
#.1.3.6.1.4.1.9.9.106.1.2.1.1.13.1.192  192.168.10.5 <- ip Router 1 int 1
#.1.3.6.1.4.1.9.9.106.1.2.1.1.13.7.193  172.20.10.21 <- ip Router 2 int 7
#.1.3.6.1.4.1.9.9.106.1.2.1.1.14.1.192  192.168.10.6 <- ip Router 1 int 1
#.1.3.6.1.4.1.9.9.106.1.2.1.1.14.7.193  172.20.10.22 <- ip Router 2 int 7
#.1.3.6.1.4.1.9.9.106.1.2.1.1.15.1.192  6     <- group #1 "standby" state
#.1.3.6.1.4.1.9.9.106.1.2.1.1.15.7.193  6     <- group #2 "standby" state
#.1.3.6.1.4.1.9.9.106.1.2.1.1.16.1.192  "00 00 0C 07 AC C0 "
#.1.3.6.1.4.1.9.9.106.1.2.1.1.16.7.193  "00 00 0C 07 AC C1 "
#.1.3.6.1.4.1.9.9.106.1.2.1.1.17.1.192  1
#.1.3.6.1.4.1.9.9.106.1.2.1.1.17.7.193  1


# we'll be alerting if the state is not either 5 or 6.
# We could also not inventorize if the state isn't 5/6 but
# since you have to configure a group, to even show up in the
# MIB it's supposedly ok to alert if something isn't right there.
# otherwise modify the inventory.
hsrp_states = { 1: "initial", 2: "learn", 3: "listen", 4: "speak", 5: "standby", 6: "active" }


def inventory_cisco_hsrp(info):
    inventory = []
    for line in info:
        hsrp_grp_entry, vip, actrouter, sbrouter, hsrp_state, vmac = line
        interface_index, hsrp_grp = hsrp_grp_entry.split(".")
        hsrp_state = int(hsrp_state)
        # if the group is in a working state (both routers see and talk to each other),
        # inventorize HSRP group name+IP and the standby state as seen from "this" box.
        if hsrp_state in [ 5, 6 ]:
            vip_grp = "%s-%s" % ( vip, hsrp_grp )
            inventory.append( (vip_grp, (hsrp_grp, hsrp_state)) )

    return inventory


def check_cisco_hsrp(item, params, info):

    hsrp_grp_wanted, hsrp_state_wanted = params

    for line in info:
        hsrp_grp_entry, vip, actrouter, sbrouter, hsrp_state, vmac = line
        interface_index, hsrp_grp = hsrp_grp_entry.split(".")
        hsrp_state = int(hsrp_state)

        if "-" in item:
            vip_grp = "%s-%s" % ( vip, hsrp_grp )
        else:
            vip_grp = vip

        if vip_grp == item:
            # FIXME: This should be shorter.
            # Validate that we the inventorized state is a "good one"
            # if it's also the one we have now, then we're fine.

            if    hsrp_state_wanted == 5  and hsrp_state == hsrp_state_wanted:
                state = 0
                msgtxt = "Redundancy Group %s is OK" %  vip_grp
            elif  hsrp_state_wanted == 6  and hsrp_state == hsrp_state_wanted:
                state = 0
                msgtxt = "Redundancy Group %s is OK" % vip_grp
            # otherwise if it's a good one, but flipped, then we are in a failover
            elif hsrp_state == 5 or hsrp_state == 6:
                state = 1
                msgtxt = "Redundancy Group %s has failed over" % hsrp_grp
            # anything else must be a non-operative state already
            else:
                state = 2
                msgtxt = "Redundancy Group %s has status %s" % ( hsrp_grp, hsrp_states[hsrp_state])

            return (state, msgtxt)

    return (3, "HSRP Group not found in Agent output" )



# FIXME: Outdated format. Fix after discussing WATO options.
check_info["cisco_hsrp"] = (check_cisco_hsrp, "HSRP Group %s", 0, inventory_cisco_hsrp)

snmp_info["cisco_hsrp"] = \
   ( ".1.3.6.1.4.1.9.9.106.1.2.1.1", [
      OID_END,
      "11", # cHsrpGrpVirtualIpAddr
      "13", # cHsrpGrpActiveRouter
      "14", # cHsrpGrpStandbyRouter
      "15", # cHsrpGrpStandbyState
      "16", # cHsrpGrpVirtualMacAddr
    ])

# We can't scan for the HSRP table since the entries are indexed
# based on information we dont have without fetching all of it
# Instead we use the HSRP timeout
snmp_scan_functions["cisco_hsrp"] = lambda oid: "cisco" in oid(".1.3.6.1.2.1.1.1.0").lower() and oid(".1.3.6.1.4.1.9.9.106.1.1.1.0")
