#
# NUT monitor

test nut {
    static set name "nutups";
    static set features;

    # these are defaults describing some test parameters

    # re-discover every 120 minutes
    set discover_refresh 120;
    # after a discover failure retry every 10 minutes
    set discover_retry 10;
    # monitor every 5 minutes by default
    set frequency 5;
    # report as item "disk"
    pernode set report_item "ups";
    set host "set by uxmon";
    set alias "set by uxmon";
    # do not send perf variables by default
    set perf_frequency 0;

    # the module we get our configuration from
    static set domain nut;

    # if upsnames contains a list of UPS names we will only monitor those
    set upsnames;
    # ups names which are not reported
    static set avoid_upsnames;

    # just declare a few variables here
    set thismonitor;

    pernode set optional_info;

    pernode set ups.name;
    pernode set ups.model;
    pernode set ups.mfr;

    pernode set monitored;
    pernode set formerly_monitored;
    pernode set former_name;

    static set default_chargefail 30%;
    static set default_chargewarn 90%;
    static set default_status OL;
    static set default_loadfail 95%;
    static set default_loadwarn 85%;
    static set default_runtimefail 360;
    static set default_runtimewarn 600;

    static set arguments
	"chargefail:percentage:Battery Charge Fail level - Big Sister panics (red) if battery charge goes below this level (default: ${default_chargefail})"
	"chargewarn:percentage:Battery Charge Warn level - Big Sister warns (yellow) if battery charge goes below this level (default: ${default_chargewarn})"
	"runtimefail:percentage:Battery Load Fail level - Big Sister panics (red) if UPS runtime goes above this level (default: ${default_runtimefail})"
	"runtimewarn:percentage:Battery Load Warn level - Big Sister warns (yellow) if UPS runtime goes below this level (default: ${default_runtimewarn})"
	"loadfail:percentage:Battery Load Fail level - Big Sister panics (red) if UPS load goes above this level (default: ${default_loadfail})"
	"loadwarn:percentage:Battery Load Warn level - Big Sister warns (yellow) if UPS load goes above this level (default: ${default_loadwarn})"
	"status:string:Normal Status - Big Sister will warn (yellow) if status of the UPS does not equal this status (default: ${default_status})"
	"ups:@pattern:A list of UPS names"
	"perf:int:report perf data every perf minutes"
	"item:string:Item as which to report.";

    # import configuration from uxmon-net
    init {
	instance set chargefail ${default_chargefail};
	instance set chargewarn ${default_chargewarn};
	instance set loadfail ${default_loadfail};
	instance set loadwarn ${default_loadwarn};
	instance set runtimefail ${default_runtimefail};
	instance set runtimewarn ${default_runtimewarn};
	instance set checkstatus ${default_status};
	instance import ups upsnames;
	instance import chargefail;
	instance import chargewarn;
	instance import loadfail;
	instance import loadwarn;
	instance import status checkstatus;
	instance import perf perf_frequency;
	pernode import item report_item;
    }

    # walk the relevant data structures and do some pre-processing
    pernode discover {
	get @${domain}.name @${domain}.ups.mfr @${domain}.ups.model;
	set ups.name ${${domain}.name};
	set ups.mfr ${${domain}.ups.mfr};
	set ups.model ${${domain}.ups.model};
	debug 5 ups ${ups.name} manufacturer ${ups.mfr} model ${ups.model};
    }

    # select the entities this instance will monitor
    discover {
	set oldmonitor ${thismonitor};
	set monitored remove( ${monitored}, ${oldmonitor} );

	set index ${ups.name};
	select thismonitor index
	    ( null( ${upsnames} ) || contains_pattern( ${upsnames}, ${ups.name[${i}]} ) )
	       && not( contains( ${monitored}, ${i} ) ) )
	       && not( contains_pattern( ${avoid_upsnames}, ${ups.name[${i}]} ) );

	set monitored ${monitored} ${thismonitor};
    };

    pernode postdiscover {
	debug 3 "currently monitored:" ${monitored};
	set notmonitored_anymore unmonitored( ${formerly_monitored}, ${monitored}, ${former_name} );
	set newly_monitored nowmonitored( ${formerly_monitored}, ${monitored}, ${ups.name} );
	event "notice" ${notmonitored_anymore};
	event "notice" ${newly_monitored};
	pernode set formerly_monitored ${monitored};
	pernode set former_name ${ups.name};
    }

    pernode monitor {
	# clear variables
    	pernode set ups.charge;
    	pernode set ups.load;
    	pernode set ups.runtime;
    	pernode set ups.voltage;
    	pernode set ups.status;
    }

    monitor {
	get ${domain}.battery.charge[${thismonitor}]
	    ${domain}.battery.voltage[${thismonitor}]
	    ${domain}.battery.runtime[${thismonitor}]
	    ${domain}.ups.status[${thismonitor}]
	    ${domain}.ups.load[${thismonitor}];

        debug 3 LOAD ${${domain}.ups.load};
	set ups.charge ${${domain}.battery.charge};
	set ups.voltage ${${domain}.battery.voltage};
	set ups.runtime ${${domain}.battery.runtime};
	set ups.status ${${domain}.ups.status};
	set ups.load ${${domain}.ups.load};
    };

    pernode report {
	debug 3 monitored items are ${monitored};
	set text;
	for text monitored pad( ${ups.name[${i}]}, 15, "l" )
		pad( ${ups.status[${i}]}, 8, "r" )
		pad( format_percentage( ${ups.charge[${i}]} ), 8, "r" )
		pad( format_percentage( ${ups.load[${i}]} ), 7, "r" )
		pad( ${ups.runtime[${i}]}, 9, "r" )
		pad( ${ups.voltage[${i}]}, 10, "r" ) 
		" " ${ups.mfr[${i}]} " " ${ups.model[${i}]} "\n";
	debug 3 ${text};
	set head pad( "UPS", 15, "l" )
		pad( "Status", 8, "r" )
		pad( "Charge", 8, "r" )
		pad( "Load", 7, "r" )
		pad( "Runtime", 9, "r" )
		pad( "BatVolt.", 10, "r" )
		" Model\n\n";
	status purple null( ${monitored} ) "no UPS monitored";
	comment "html" "<HR></HR><PRE><strong>" ${head} </strong> ${text} "</PRE>";
    };

    report for thismonitor {
	status red in_range( 0, ${chargefail}, ${ups.charge[${p}]}, ${ups.charge[${p}]} )
	    "&red" " " ${ups.name[${p}]} " charge CRITICAL";
	status yellow in_range( 0, ${chargewarn}, ${ups.charge[${p}]}, ${ups.charge[${p}]} )
	    "&yellow" " " ${ups.name[${p}]} " charge LOW";
	status purple null( ${ups.charge[${p}]} )
	    "&purple " ${ups.name[${p}]} " no info available";
	status green 1
	    "&green" " " ${ups.name[${p}]} " charge OK";
    };

    report for thismonitor {
	status red in_range( ${loadfail}, "100%", ${ups.load[${p}]}, ${ups.load[${p}]} )
	    "&red" " " ${ups.name[${p}]} " load CRITICAL";
	status yellow in_range( ${loadwarn}, "100%", ${ups.load[${p}]}, ${ups.load[${p}]} )
	    "&yellow" " " ${ups.name[${p}]} " load HIGH";
	status purple null( ${ups.load[${p}]} )
	    "&purple " ${ups.name[${p}]} " no info available";
	status green 1
	    "&green" " " ${ups.name[${p}]} " load OK";
    };

    report for thismonitor {
	status red in_range( 0, ${runtimefail}, ${ups.runtime[${p}]}, ${ups.runtime[${p}]} )
	    "&red" " " ${ups.name[${p}]} " runtime CRITICAL";
	status yellow in_range( 0, ${runtimewarn}, ${ups.runtime[${p}]}, ${ups.runtime[${p}]} )
	    "&yellow" " " ${ups.name[${p}]} " runtime LOW";
	status purple null( ${ups.runtime[${p}]} )
	    "&purple " ${ups.name[${p}]} " no info available";
	status green 1
	    "&green" " " ${ups.name[${p}]} " runtime OK";
    };

    report for thismonitor {
	status yellow ( not( contains( ${checkstatus}, "" ) ) && not( contains( ${ups.status[${p}]}, ${checkstatus} ) ) )
	    "&yellow" " " ${ups.name[${p}]} " status UNNORMAL";
	status purple null( ${ups.status[${p}]} )
	    "&purple " ${ups.name[${p}]} " no info available";
	status green 1
	    "&green" " " ${ups.name[${p}]} " status OK";
    };

    perf {
        export sometimes ups.name, ${ups.name[${thismonitor}]};
        export sometimes ups.mfr, ${ups.mfr[${thismonitor}]};
        export sometimes ups.model, ${ups.model[${thismonitor}]};

        export always ups.load, ${ups.load[${thismonitor}]};
        export always ups.charge, ${ups.charge[${thismonitor}]};
        export always ups.runtime, ${ups.runtime[${thismonitor}]};
        export always ups.voltage, ${ups.voltage[${thismonitor}]};
    };

    pernode unconfigure {
	pernode set monitored;
	pernode set ups.name;
	pernode set ups.mfr;
	pernode set ups.model;
	pernode set ups.load;
	pernode set ups.charge;
	pernode set ups.runtime;
	pernode set ups.voltage;
	pernode set monitored;
    }
}
