#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
symmetrix (thin) pool-usage check

usage:

    me [symmetrix-id] [symmetrix-id2]

"""
import sys,logging
import StringIO

LOGFILE = "/tmp/bla"

logging.basicConfig(
#    filename=LOGFILE,
#    level=logging.DEBUG,
    level=logging.INFO,
    format= "%(asctime)s [%(levelname)-8s] %(message)s" )

logger = logging.getLogger("checksympool")

### EDITME ###

SYMCLI_DIR='/opt/emc/SYMCLI/bin/'

sids = ['123','223']
thresh_full = {'_default' : [60.0,80.0], 'R6' : [60.0,80.0] }

### END EDITME ###

poolstatus = {}
status_codes = {0: 'OK', 1 : 'WARNING', 2 : 'CRITICAL'}

orig_stderr = sys.stderr
sys.stderr = sys.stdout # nrpe reads seems to read stdout only

__author__ = 'sven hessenmüller (sven.hessenmueller@gmail.com)'
__version__ = '0.0.5'
__date__ = '20120322'
__copyright__ = 'Copyright (c) 2012 Sven Hessenmüller'
__license__ = "GPL"


def execCmd(sCmd):
    """
    executes a given Command

    returns
        rc, output
    """
    import subprocess as sub

    p = sub.Popen([sCmd], shell=True, stdout=sub.PIPE, stderr=sub.STDOUT)
    #output = p.stdout.read()
    output = p.stdout.readlines()
    p.wait()
    rc = p.returncode

    if rc != 0:
        logger.critical("command failed with rc %i: %s" % (rc,sCmd))
        logger.critical("got %s" % (output))

    return rc, output

def parseXML(f):
    """
    """
    import xml.etree.ElementTree as etree

    if (isinstance(f,file) or isinstance(f,StringIO.StringIO)): # file-like-object / handle
        f.seek(0) # just to make sure we're on the beginning of content

    tree = etree.parse(f)
    root = tree.getroot()

    dR = {}

    for xRec in root.findall("Symmetrix/DevicePool"):
        pname = xRec.find("pool_name").text
        ptype = xRec.find("pool_type").text
        pstate = xRec.find("pool_state").text
        pcapacity_enabled_gb = float(xRec.find("total_enabled_tracks_gb").text)
        pfull = float(xRec.find("percent_full").text)
       
        logger.debug("%s %s %s %s" % (pname, ptype, pstate, pfull))

        if pstate != "Enabled": continue

        dR[pname] = {}
        dR[pname]['type'] = ptype
        dR[pname]['state'] = pstate
        dR[pname]['full'] = pfull
        dR[pname]['capacity_enabled_gb'] = pcapacity_enabled_gb

    return dR



if __name__ == '__main__':

    if len(sys.argv) > 1: 
        logger.info("overwriting predefined list of sids (%s) by cli-args" % sids)
        sids = []
        for arg in sys.argv[1:]:
            sids.append(arg)

    for sid in sids:
        sCmd = '%ssymcfg -sid %s list -pool -output xml' % (SYMCLI_DIR,sid)
        fout = '/tmp/checkpool.%s.xml' % sid
        poolstatus[sid] = {}
        result_ok = []
        result_warn = []
        result_crit = []
        result_41line = [[],['| ']] # all infos in one line + performance_data format, see http://docs.icinga.org/latest/de/perfdata.html
        status_code = 0

        rc, output = execCmd(sCmd)

#        f = open(fout,'w')
#        for l in output:
#            if len(l.strip()) > 0: f.write(l)
#        f.close()

        fout_mem = StringIO.StringIO()
        for l in output:
            if len(l.strip()) > 0: fout_mem.write(l)
        fout_mem.seek(0)

        
        if rc == 0:
	    poolstatus[sid] = parseXML(fout_mem)
        else:
            raise Exception("sorry got RC %s: %s" % (rc, output))

    logger.debug(poolstatus)

    for sid in sids:
        result_41line[0].append("%s " % sid)
        for pool in sorted(poolstatus[sid]):
            sLine = "%s ...%s pool %s " % (sid,poolstatus[sid][pool]['type'],pool)

            if thresh_full.has_key(pool):
                twarn = thresh_full[pool][0]
                tcrit = thresh_full[pool][1]
            else:
                twarn = thresh_full['_default'][0]
                tcrit = thresh_full['_default'][1]

            full = poolstatus[sid][pool]['full']
            capgb = poolstatus[sid][pool]['capacity_enabled_gb']

            if full > tcrit:
                sLine += "CRITICAL %s%% full (%s gb enabled)" % (full,capgb)
                result_crit.append(sLine)

            elif full > twarn:
                sLine += "WARNING %s%% full (%s gb enabled)" % (full,capgb)
                result_warn.append(sLine)

            else:
                #sLine += "OK %s%% full (%s gb enabled) | %s=%s%%" % (full,capgb,pool,full)
                sLine += "OK %s%% full (%s gb enabled)" % (full,capgb)
                result_ok.append(sLine)


            result_41line[0].append("%s %s%% " % (pool, full))
            #result_41line[1].append("%s=%s%%;%s;%s;%s;%s " % (pool, full,twarn,tcrit,0.0,100.0))
            result_41line[1].append("%s=%s%%;%s;%s " % (pool, full,twarn,tcrit))


    if len(result_crit) > 0:
        status_code = 2
    elif len(result_warn) > 0:
        status_code = 1
    
    print status_codes[status_code] + " " + "".join(result_41line[0]), "".join(result_41line[1])
            
    for l in result_crit + result_warn + result_ok: print l

    sys.exit(status_code)

